Compare commits
14 Commits
64e5eddfd5
...
main
Author | SHA1 | Date | |
---|---|---|---|
080fb7d077 | |||
57c59c911a | |||
acab16e101 | |||
9a9c932262 | |||
004d442e67 | |||
77d0d5cc81 | |||
b80a6d2623 | |||
50a38816d3 | |||
9489183b68 | |||
49dffff1bf | |||
82d77e2b8d | |||
851b891a8a | |||
249a6d6074 | |||
2c61b9ce8d |
9
.cursor/rules/rules1.mdc
Normal file
9
.cursor/rules/rules1.mdc
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
description: To remember for every prompts
|
||||||
|
globs:
|
||||||
|
alwaysApply: false
|
||||||
|
---
|
||||||
|
Le plus important : Repondre en français. Toujours appliquer les modification au code sauf si le message commence par "QUESTION :"
|
||||||
|
|
||||||
|
|
||||||
|
Projet d'ERP pour une entreprise d'événemetiel. Flutter, Dart
|
5
em2rp/.firebaserc
Normal file
5
em2rp/.firebaserc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"default": "em2rp-951dc"
|
||||||
|
}
|
||||||
|
}
|
@ -1 +1,38 @@
|
|||||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"em2rp-951dc","appId":"1:341201262902:android:8c9a9e340ecb58665a3b97","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"em2rp-951dc","configurations":{"android":"1:341201262902:android:8c9a9e340ecb58665a3b97","ios":"1:341201262902:ios:767281c23dd9e76a5a3b97","macos":"1:341201262902:ios:767281c23dd9e76a5a3b97","web":"1:341201262902:web:bb70b5ff45df80935a3b97","windows":"1:341201262902:web:faceb51cb184a2875a3b97"}}}}}}
|
{
|
||||||
|
"flutter": {
|
||||||
|
"platforms": {
|
||||||
|
"android": {
|
||||||
|
"default": {
|
||||||
|
"projectId": "em2rp-951dc",
|
||||||
|
"appId": "1:341201262902:android:8c9a9e340ecb58665a3b97",
|
||||||
|
"fileOutput": "android/app/google-services.json"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dart": {
|
||||||
|
"lib/firebase_options.dart": {
|
||||||
|
"projectId": "em2rp-951dc",
|
||||||
|
"configurations": {
|
||||||
|
"android": "1:341201262902:android:8c9a9e340ecb58665a3b97",
|
||||||
|
"ios": "1:341201262902:ios:767281c23dd9e76a5a3b97",
|
||||||
|
"macos": "1:341201262902:ios:767281c23dd9e76a5a3b97",
|
||||||
|
"web": "1:341201262902:web:bb70b5ff45df80935a3b97",
|
||||||
|
"windows": "1:341201262902:web:faceb51cb184a2875a3b97"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"functions": [
|
||||||
|
{
|
||||||
|
"source": "functions",
|
||||||
|
"codebase": "default",
|
||||||
|
"ignore": [
|
||||||
|
"node_modules",
|
||||||
|
".git",
|
||||||
|
"firebase-debug.log",
|
||||||
|
"firebase-debug.*.log",
|
||||||
|
"*.local"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
rules_version = '2';
|
|
||||||
|
|
||||||
service cloud.firestore {
|
|
||||||
match /databases/{database}/documents {
|
|
||||||
// Fonction pour vérifier si l'utilisateur est authentifié
|
|
||||||
function isAuthenticated() {
|
|
||||||
return request.auth != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getUserRole() {
|
|
||||||
let userData = get(/databases/$(database)/documents/users/$(request.auth.uid)).data;
|
|
||||||
return userData != null ? userData.role : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour vérifier si l'utilisateur est un admin
|
|
||||||
function isAdmin() {
|
|
||||||
return isAuthenticated() && getUserRole() == 'ADMIN';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isOwner(userId) {
|
|
||||||
return isAuthenticated() && request.auth.uid == userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nouvelle fonction pour vérifier si un CREW est assigné à un événement du client
|
|
||||||
function isAssignedToClientEvent(clientId) {
|
|
||||||
let events = getAfter(/databases/$(database)/documents/events)
|
|
||||||
.where("clientId", "==", clientId)
|
|
||||||
.where("assignedUsers." + request.auth.uid, "==", true).limit(1);
|
|
||||||
return events.size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour vérifier si c'est le premier utilisateur
|
|
||||||
function isFirstUser() {
|
|
||||||
return !exists(/databases/$(database)/documents/users);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fonction pour vérifier si c'est une mise à jour de l'UID
|
|
||||||
function isUidUpdate() {
|
|
||||||
return request.resource.data.diff(resource.data).affectedKeys().hasOnly(['uid']);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Règles pour la collection users
|
|
||||||
match /users/{userId} {
|
|
||||||
allow read: if isAuthenticated() && (isAdmin() || isOwner(userId));
|
|
||||||
// Permettre la création si admin OU si l'utilisateur crée son propre document
|
|
||||||
allow create: if isAdmin() || (isAuthenticated() && request.auth.uid == userId);
|
|
||||||
allow update: if isAdmin() ||
|
|
||||||
(isOwner(userId) &&
|
|
||||||
request.resource.data.diff(resource.data).affectedKeys()
|
|
||||||
.hasOnly(['phoneNumber', 'profilePhotoUrl', 'firstName', 'lastName', 'role']));
|
|
||||||
allow delete: if isAdmin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Règles pour la collection clients
|
|
||||||
match /clients/{clientId} {
|
|
||||||
// Lecture :
|
|
||||||
// - Les admins peuvent tout voir
|
|
||||||
// - Les CREW ne peuvent voir que les clients liés à leurs événements
|
|
||||||
allow read: if isAdmin() ||
|
|
||||||
(getUserRole() == 'CREW' && isAssignedToClientEvent(clientId));
|
|
||||||
|
|
||||||
// Création, modification et suppression : Seuls les admins
|
|
||||||
allow create, update, delete: if isAdmin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Règles pour la collection events (prestations)
|
|
||||||
match /events/{eventId} {
|
|
||||||
allow read: if isAdmin() ||
|
|
||||||
(isAuthenticated() && (resource.data.assignedUsers[request.auth.uid] == true));
|
|
||||||
allow create, update: if isAdmin();
|
|
||||||
allow delete: if isAdmin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Règles pour la collection quotes (devis)
|
|
||||||
match /quotes/{quoteId} {
|
|
||||||
allow read, write: if isAdmin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Règles pour la collection invoices (factures)
|
|
||||||
match /invoices/{invoiceId} {
|
|
||||||
allow read, write: if isAdmin();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Règles pour les autres collections
|
|
||||||
match /{document=**} {
|
|
||||||
// Par défaut, refuser l'accès
|
|
||||||
allow read, write: if false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
28
em2rp/functions/.eslintrc.js
Normal file
28
em2rp/functions/.eslintrc.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
es6: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
"ecmaVersion": 2018,
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
"eslint:recommended",
|
||||||
|
"google",
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
"no-restricted-globals": ["error", "name", "length"],
|
||||||
|
"prefer-arrow-callback": "error",
|
||||||
|
"quotes": ["error", "double", {"allowTemplateLiterals": true}],
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["**/*.spec.*"],
|
||||||
|
env: {
|
||||||
|
mocha: true,
|
||||||
|
},
|
||||||
|
rules: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
globals: {},
|
||||||
|
};
|
2
em2rp/functions/.gitignore
vendored
Normal file
2
em2rp/functions/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
*.local
|
73
em2rp/functions/index.js
Normal file
73
em2rp/functions/index.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/**
|
||||||
|
* Import function triggers from their respective submodules:
|
||||||
|
*
|
||||||
|
* const {onCall} = require("firebase-functions/v2/https");
|
||||||
|
* const {onDocumentWritten} = require("firebase-functions/v2/firestore");
|
||||||
|
*
|
||||||
|
* See a full list of supported triggers at https://firebase.google.com/docs/functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
const {onRequest} = require("firebase-functions/v2/https");
|
||||||
|
const logger = require("firebase-functions/logger");
|
||||||
|
|
||||||
|
// Create and deploy your first functions
|
||||||
|
// https://firebase.google.com/docs/functions/get-started
|
||||||
|
|
||||||
|
// exports.helloWorld = onRequest((request, response) => {
|
||||||
|
// logger.info("Hello logs!", {structuredData: true});
|
||||||
|
// response.send("Hello from Firebase!");
|
||||||
|
// });
|
||||||
|
|
||||||
|
const functions = require('firebase-functions');
|
||||||
|
const admin = require('firebase-admin');
|
||||||
|
const { Storage } = require('@google-cloud/storage');
|
||||||
|
admin.initializeApp();
|
||||||
|
const storage = new Storage();
|
||||||
|
|
||||||
|
// Nouvelle version HTTP sécurisée
|
||||||
|
exports.moveEventFileV2 = functions.https.onRequest(async (req, res) => {
|
||||||
|
// Ajout des headers CORS
|
||||||
|
res.set('Access-Control-Allow-Origin', '*');
|
||||||
|
res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
||||||
|
if (req.method === 'OPTIONS') {
|
||||||
|
res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
||||||
|
res.status(204).send('');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Vérification du token Firebase dans l'en-tête Authorization
|
||||||
|
let uid = null;
|
||||||
|
if (req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
|
||||||
|
const idToken = req.headers.authorization.split('Bearer ')[1];
|
||||||
|
try {
|
||||||
|
const decodedToken = await admin.auth().verifyIdToken(idToken);
|
||||||
|
uid = decodedToken.uid;
|
||||||
|
} catch (e) {
|
||||||
|
res.status(401).json({ error: 'Invalid token' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.status(401).json({ error: 'No token provided' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { sourcePath, destinationPath } = req.body.data || {};
|
||||||
|
if (!sourcePath || !destinationPath) {
|
||||||
|
res.status(400).json({ error: 'Source and destination paths are required.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bucketName = admin.storage().bucket().name;
|
||||||
|
const bucket = storage.bucket(bucketName);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await bucket.file(sourcePath).copy(bucket.file(destinationPath));
|
||||||
|
await bucket.file(sourcePath).delete();
|
||||||
|
const [url] = await bucket.file(destinationPath).getSignedUrl({
|
||||||
|
action: 'read',
|
||||||
|
expires: '03-01-2500',
|
||||||
|
});
|
||||||
|
res.status(200).json({ url });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
7142
em2rp/functions/package-lock.json
generated
Normal file
7142
em2rp/functions/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
em2rp/functions/package.json
Normal file
26
em2rp/functions/package.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "functions",
|
||||||
|
"description": "Cloud Functions for Firebase",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint .",
|
||||||
|
"serve": "firebase emulators:start --only functions",
|
||||||
|
"shell": "firebase functions:shell",
|
||||||
|
"start": "npm run shell",
|
||||||
|
"deploy": "firebase deploy --only functions",
|
||||||
|
"logs": "firebase functions:log"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "22"
|
||||||
|
},
|
||||||
|
"main": "index.js",
|
||||||
|
"dependencies": {
|
||||||
|
"firebase-admin": "^12.6.0",
|
||||||
|
"firebase-functions": "^6.0.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^8.15.0",
|
||||||
|
"eslint-config-google": "^0.14.0",
|
||||||
|
"firebase-functions-test": "^3.1.0"
|
||||||
|
},
|
||||||
|
"private": true
|
||||||
|
}
|
@ -13,8 +13,9 @@ import 'views/user_management_page.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'providers/local_user_provider.dart';
|
import 'providers/local_user_provider.dart';
|
||||||
import 'services/user_service.dart';
|
import 'services/user_service.dart';
|
||||||
import 'pages/auth/reset_password_page.dart';
|
import 'views/reset_password_page.dart';
|
||||||
import 'config/env.dart';
|
import 'config/env.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@ -81,13 +82,22 @@ class MyApp extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
locale: const Locale('fr', 'FR'),
|
||||||
|
supportedLocales: const [
|
||||||
|
Locale('fr', 'FR'),
|
||||||
|
],
|
||||||
|
localizationsDelegates: const [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
home: const AutoLoginWrapper(),
|
home: const AutoLoginWrapper(),
|
||||||
routes: {
|
routes: {
|
||||||
'/login': (context) => const LoginPage(),
|
'/login': (context) => const LoginPage(),
|
||||||
'/calendar': (context) => const AuthGuard(child: CalendarPage()),
|
'/calendar': (context) => const AuthGuard(child: CalendarPage()),
|
||||||
'/my_account': (context) => const AuthGuard(child: MyAccountPage()),
|
'/my_account': (context) => const AuthGuard(child: MyAccountPage()),
|
||||||
'/user_management': (context) =>
|
'/user_management': (context) => const AuthGuard(
|
||||||
const AuthGuard(requiredRole: "ADMIN", child: UserManagementPage()),
|
requiredPermission: "view_all_users", child: UserManagementPage()),
|
||||||
'/reset_password': (context) {
|
'/reset_password': (context) {
|
||||||
final args = ModalRoute.of(context)!.settings.arguments
|
final args = ModalRoute.of(context)!.settings.arguments
|
||||||
as Map<String, dynamic>;
|
as Map<String, dynamic>;
|
||||||
|
@ -1,19 +1,54 @@
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:latlong2/latlong.dart';
|
import 'package:latlong2/latlong.dart';
|
||||||
|
|
||||||
|
enum EventStatus {
|
||||||
|
confirmed,
|
||||||
|
canceled,
|
||||||
|
waitingForApproval,
|
||||||
|
}
|
||||||
|
|
||||||
|
String eventStatusToString(EventStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
return 'CONFIRMED';
|
||||||
|
case EventStatus.canceled:
|
||||||
|
return 'CANCELED';
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
return 'WAITING_FOR_APPROVAL';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EventStatus eventStatusFromString(String? status) {
|
||||||
|
switch (status) {
|
||||||
|
case 'CONFIRMED':
|
||||||
|
return EventStatus.confirmed;
|
||||||
|
case 'CANCELED':
|
||||||
|
return EventStatus.canceled;
|
||||||
|
case 'WAITING_FOR_APPROVAL':
|
||||||
|
default:
|
||||||
|
return EventStatus.waitingForApproval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class EventModel {
|
class EventModel {
|
||||||
final String id;
|
final String id;
|
||||||
final String name;
|
final String name;
|
||||||
final String description;
|
final String description;
|
||||||
final DateTime startDateTime;
|
final DateTime startDateTime;
|
||||||
final DateTime endDateTime;
|
final DateTime endDateTime;
|
||||||
final double price;
|
final double basePrice;
|
||||||
final int installationTime;
|
final int installationTime;
|
||||||
final int disassemblyTime;
|
final int disassemblyTime;
|
||||||
final String eventTypeId;
|
final String eventTypeId;
|
||||||
final String customerId;
|
final String customerId;
|
||||||
final LatLng address;
|
final String address;
|
||||||
final List<String> workforce;
|
final double latitude;
|
||||||
|
final double longitude;
|
||||||
|
final List<DocumentReference> workforce;
|
||||||
|
final List<Map<String, String>> documents;
|
||||||
|
final List<Map<String, dynamic>> options;
|
||||||
|
final EventStatus status;
|
||||||
|
|
||||||
EventModel({
|
EventModel({
|
||||||
required this.id,
|
required this.id,
|
||||||
@ -21,21 +56,50 @@ class EventModel {
|
|||||||
required this.description,
|
required this.description,
|
||||||
required this.startDateTime,
|
required this.startDateTime,
|
||||||
required this.endDateTime,
|
required this.endDateTime,
|
||||||
required this.price,
|
required this.basePrice,
|
||||||
required this.installationTime,
|
required this.installationTime,
|
||||||
required this.disassemblyTime,
|
required this.disassemblyTime,
|
||||||
required this.eventTypeId,
|
required this.eventTypeId,
|
||||||
required this.customerId,
|
required this.customerId,
|
||||||
required this.address,
|
required this.address,
|
||||||
|
required this.latitude,
|
||||||
|
required this.longitude,
|
||||||
required this.workforce,
|
required this.workforce,
|
||||||
|
required this.documents,
|
||||||
|
this.options = const [],
|
||||||
|
this.status = EventStatus.waitingForApproval,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory EventModel.fromMap(Map<String, dynamic> map, String id) {
|
factory EventModel.fromMap(Map<String, dynamic> map, String id) {
|
||||||
final GeoPoint? geoPoint = map['Address'] as GeoPoint?;
|
|
||||||
final List<dynamic> workforceRefs = map['workforce'] ?? [];
|
final List<dynamic> workforceRefs = map['workforce'] ?? [];
|
||||||
final Timestamp? startTimestamp = map['StartDateTime'] as Timestamp?;
|
final Timestamp? startTimestamp = map['StartDateTime'] as Timestamp?;
|
||||||
final Timestamp? endTimestamp = map['EndDateTime'] as Timestamp?;
|
final Timestamp? endTimestamp = map['EndDateTime'] as Timestamp?;
|
||||||
|
|
||||||
|
final docsRaw = map['documents'] ?? [];
|
||||||
|
final docs = docsRaw is List
|
||||||
|
? docsRaw.map<Map<String, String>>((e) {
|
||||||
|
if (e is Map) {
|
||||||
|
return Map<String, String>.from(e as Map);
|
||||||
|
} else if (e is String) {
|
||||||
|
final fileName = Uri.decodeComponent(
|
||||||
|
e.split('/').last.split('?').first,
|
||||||
|
);
|
||||||
|
return {'name': fileName, 'url': e};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}).toList()
|
||||||
|
: <Map<String, String>>[];
|
||||||
|
final optionsRaw = map['options'] ?? [];
|
||||||
|
final options = optionsRaw is List
|
||||||
|
? optionsRaw.map<Map<String, dynamic>>((e) {
|
||||||
|
if (e is Map) {
|
||||||
|
return Map<String, dynamic>.from(e as Map);
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}).toList()
|
||||||
|
: <Map<String, dynamic>>[];
|
||||||
return EventModel(
|
return EventModel(
|
||||||
id: id,
|
id: id,
|
||||||
name: map['Name'] ?? '',
|
name: map['Name'] ?? '',
|
||||||
@ -43,7 +107,7 @@ class EventModel {
|
|||||||
startDateTime: startTimestamp?.toDate() ?? DateTime.now(),
|
startDateTime: startTimestamp?.toDate() ?? DateTime.now(),
|
||||||
endDateTime: endTimestamp?.toDate() ??
|
endDateTime: endTimestamp?.toDate() ??
|
||||||
DateTime.now().add(const Duration(hours: 1)),
|
DateTime.now().add(const Duration(hours: 1)),
|
||||||
price: (map['Price'] ?? 0.0).toDouble(),
|
basePrice: (map['BasePrice'] ?? map['Price'] ?? 0.0).toDouble(),
|
||||||
installationTime: map['InstallationTime'] ?? 0,
|
installationTime: map['InstallationTime'] ?? 0,
|
||||||
disassemblyTime: map['DisassemblyTime'] ?? 0,
|
disassemblyTime: map['DisassemblyTime'] ?? 0,
|
||||||
eventTypeId: map['EventType'] is DocumentReference
|
eventTypeId: map['EventType'] is DocumentReference
|
||||||
@ -52,15 +116,13 @@ class EventModel {
|
|||||||
customerId: map['customer'] is DocumentReference
|
customerId: map['customer'] is DocumentReference
|
||||||
? (map['customer'] as DocumentReference).id
|
? (map['customer'] as DocumentReference).id
|
||||||
: '',
|
: '',
|
||||||
address: geoPoint != null
|
address: map['Address'] ?? '',
|
||||||
? LatLng(geoPoint.latitude, geoPoint.longitude)
|
latitude: (map['Latitude'] ?? 0.0).toDouble(),
|
||||||
: const LatLng(0, 0),
|
longitude: (map['Longitude'] ?? 0.0).toDouble(),
|
||||||
workforce: workforceRefs.map((ref) {
|
workforce: workforceRefs.whereType<DocumentReference>().toList(),
|
||||||
if (ref is DocumentReference) {
|
documents: docs,
|
||||||
return ref.id;
|
options: options,
|
||||||
}
|
status: eventStatusFromString(map['status'] as String?),
|
||||||
return ref.toString();
|
|
||||||
}).toList(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +132,19 @@ class EventModel {
|
|||||||
'Description': description,
|
'Description': description,
|
||||||
'StartDateTime': Timestamp.fromDate(startDateTime),
|
'StartDateTime': Timestamp.fromDate(startDateTime),
|
||||||
'EndDateTime': Timestamp.fromDate(endDateTime),
|
'EndDateTime': Timestamp.fromDate(endDateTime),
|
||||||
'Price': price,
|
'BasePrice': basePrice,
|
||||||
'InstallationTime': installationTime,
|
'InstallationTime': installationTime,
|
||||||
'DisassemblyTime': disassemblyTime,
|
'DisassemblyTime': disassemblyTime,
|
||||||
'EventType': eventTypeId,
|
'EventType': eventTypeId,
|
||||||
'customer': customerId,
|
'customer': customerId,
|
||||||
'Address': GeoPoint(address.latitude, address.longitude),
|
'Address': address,
|
||||||
|
'Position': GeoPoint(latitude, longitude),
|
||||||
|
'Latitude': latitude,
|
||||||
|
'Longitude': longitude,
|
||||||
'workforce': workforce,
|
'workforce': workforce,
|
||||||
|
'documents': documents,
|
||||||
|
'options': options,
|
||||||
|
'status': eventStatusToString(status),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
42
em2rp/lib/models/option_model.dart
Normal file
42
em2rp/lib/models/option_model.dart
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
|
class EventOption {
|
||||||
|
final String id;
|
||||||
|
final String name;
|
||||||
|
final String details;
|
||||||
|
final double valMin;
|
||||||
|
final double valMax;
|
||||||
|
final List<DocumentReference> eventTypes;
|
||||||
|
|
||||||
|
EventOption({
|
||||||
|
required this.id,
|
||||||
|
required this.name,
|
||||||
|
required this.details,
|
||||||
|
required this.valMin,
|
||||||
|
required this.valMax,
|
||||||
|
required this.eventTypes,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory EventOption.fromMap(Map<String, dynamic> map, String id) {
|
||||||
|
return EventOption(
|
||||||
|
id: id,
|
||||||
|
name: map['name'] ?? '',
|
||||||
|
details: map['details'] ?? '',
|
||||||
|
valMin: (map['valMin'] ?? 0.0).toDouble(),
|
||||||
|
valMax: (map['valMax'] ?? 0.0).toDouble(),
|
||||||
|
eventTypes: (map['eventTypes'] as List<dynamic>? ?? [])
|
||||||
|
.whereType<DocumentReference>()
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'name': name,
|
||||||
|
'details': details,
|
||||||
|
'valMin': valMin,
|
||||||
|
'valMax': valMax,
|
||||||
|
'eventTypes': eventTypes,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,100 +1,28 @@
|
|||||||
enum Permission {
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
// Permissions liées aux prestations
|
|
||||||
viewAllEvents, // Voir toutes les prestations
|
|
||||||
viewAssignedEvents, // Voir uniquement les prestations assignées
|
|
||||||
editEvents, // Modifier les prestations
|
|
||||||
deleteEvents, // Supprimer les prestations
|
|
||||||
assignCrew, // Assigner des membres d'équipe aux prestations
|
|
||||||
|
|
||||||
// Permissions liées aux finances
|
class RoleModel {
|
||||||
viewPrices, // Voir les prix
|
final String id;
|
||||||
editPrices, // Modifier les prix
|
|
||||||
viewQuotes, // Voir les devis
|
|
||||||
createQuotes, // Créer des devis
|
|
||||||
editQuotes, // Modifier les devis
|
|
||||||
viewInvoices, // Voir les factures
|
|
||||||
createInvoices, // Créer des factures
|
|
||||||
editInvoices, // Modifier les factures
|
|
||||||
|
|
||||||
// Permissions liées aux utilisateurs
|
|
||||||
viewUsers, // Voir les utilisateurs
|
|
||||||
editUsers, // Modifier les utilisateurs
|
|
||||||
deleteUsers, // Supprimer les utilisateurs
|
|
||||||
|
|
||||||
// Permissions liées aux clients
|
|
||||||
viewClients, // Voir les clients
|
|
||||||
editClients, // Modifier les clients
|
|
||||||
deleteClients, // Supprimer les clients
|
|
||||||
}
|
|
||||||
|
|
||||||
class Role {
|
|
||||||
final String name;
|
final String name;
|
||||||
final Set<Permission> permissions;
|
final List<String> permissions;
|
||||||
|
|
||||||
const Role({
|
RoleModel({
|
||||||
|
required this.id,
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.permissions,
|
required this.permissions,
|
||||||
});
|
});
|
||||||
|
|
||||||
bool hasPermission(Permission permission) => permissions.contains(permission);
|
factory RoleModel.fromMap(Map<String, dynamic> map, String id) {
|
||||||
|
return RoleModel(
|
||||||
bool hasAllPermissions(List<Permission> requiredPermissions) {
|
id: id,
|
||||||
return requiredPermissions
|
name: map['name'] ?? '',
|
||||||
.every((permission) => permissions.contains(permission));
|
permissions: List<String>.from(map['permissions'] ?? []),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAnyPermission(List<Permission> requiredPermissions) {
|
Map<String, dynamic> toMap() {
|
||||||
return requiredPermissions
|
return {
|
||||||
.any((permission) => permissions.contains(permission));
|
'name': name,
|
||||||
|
'permissions': permissions,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Roles {
|
|
||||||
static const admin = Role(
|
|
||||||
name: 'ADMIN',
|
|
||||||
permissions: {
|
|
||||||
// Toutes les permissions pour l'administrateur
|
|
||||||
Permission.viewAllEvents,
|
|
||||||
Permission.viewAssignedEvents,
|
|
||||||
Permission.editEvents,
|
|
||||||
Permission.deleteEvents,
|
|
||||||
Permission.assignCrew,
|
|
||||||
Permission.viewPrices,
|
|
||||||
Permission.editPrices,
|
|
||||||
Permission.viewQuotes,
|
|
||||||
Permission.createQuotes,
|
|
||||||
Permission.editQuotes,
|
|
||||||
Permission.viewInvoices,
|
|
||||||
Permission.createInvoices,
|
|
||||||
Permission.editInvoices,
|
|
||||||
Permission.viewUsers,
|
|
||||||
Permission.editUsers,
|
|
||||||
Permission.deleteUsers,
|
|
||||||
Permission.viewClients,
|
|
||||||
Permission.editClients,
|
|
||||||
Permission.deleteClients,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
static const crew = Role(
|
|
||||||
name: 'CREW',
|
|
||||||
permissions: {
|
|
||||||
// Permissions limitées pour l'équipe
|
|
||||||
Permission.viewAssignedEvents,
|
|
||||||
Permission.viewClients,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
static Role fromString(String roleName) {
|
|
||||||
switch (roleName.toUpperCase()) {
|
|
||||||
case 'ADMIN':
|
|
||||||
return admin;
|
|
||||||
case 'CREW':
|
|
||||||
return crew;
|
|
||||||
default:
|
|
||||||
return crew; // Par défaut, on donne les permissions minimales
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static List<Role> values = [admin, crew];
|
|
||||||
}
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
class UserModel {
|
class UserModel {
|
||||||
final String uid;
|
final String uid;
|
||||||
final String firstName;
|
final String firstName;
|
||||||
@ -19,11 +21,20 @@ class UserModel {
|
|||||||
|
|
||||||
// Convertit une Map (Firestore) en UserModel
|
// Convertit une Map (Firestore) en UserModel
|
||||||
factory UserModel.fromMap(Map<String, dynamic> data, String uid) {
|
factory UserModel.fromMap(Map<String, dynamic> data, String uid) {
|
||||||
|
String roleString;
|
||||||
|
final roleField = data['role'];
|
||||||
|
if (roleField is String) {
|
||||||
|
roleString = roleField;
|
||||||
|
} else if (roleField is DocumentReference) {
|
||||||
|
roleString = roleField.id;
|
||||||
|
} else {
|
||||||
|
roleString = 'USER';
|
||||||
|
}
|
||||||
return UserModel(
|
return UserModel(
|
||||||
uid: uid,
|
uid: uid,
|
||||||
firstName: data['firstName'] ?? '',
|
firstName: data['firstName'] ?? '',
|
||||||
lastName: data['lastName'] ?? '',
|
lastName: data['lastName'] ?? '',
|
||||||
role: data['role'] ?? 'USER',
|
role: roleString,
|
||||||
profilePhotoUrl: data['profilePhotoUrl'] ?? '',
|
profilePhotoUrl: data['profilePhotoUrl'] ?? '',
|
||||||
email: data['email'] ?? '',
|
email: data['email'] ?? '',
|
||||||
phoneNumber: data['phoneNumber'] ?? '',
|
phoneNumber: data['phoneNumber'] ?? '',
|
||||||
@ -35,7 +46,7 @@ class UserModel {
|
|||||||
return {
|
return {
|
||||||
'firstName': firstName,
|
'firstName': firstName,
|
||||||
'lastName': lastName,
|
'lastName': lastName,
|
||||||
'role': role,
|
'role': FirebaseFirestore.instance.collection('roles').doc(role),
|
||||||
'profilePhotoUrl': profilePhotoUrl,
|
'profilePhotoUrl': profilePhotoUrl,
|
||||||
'email': email,
|
'email': email,
|
||||||
'phoneNumber': phoneNumber,
|
'phoneNumber': phoneNumber,
|
||||||
|
@ -11,25 +11,33 @@ class EventProvider with ChangeNotifier {
|
|||||||
bool get isLoading => _isLoading;
|
bool get isLoading => _isLoading;
|
||||||
|
|
||||||
// Récupérer les événements pour un utilisateur spécifique
|
// Récupérer les événements pour un utilisateur spécifique
|
||||||
Future<void> loadUserEvents(String userId) async {
|
Future<void> loadUserEvents(String userId,
|
||||||
|
{bool canViewAllEvents = false}) async {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
print('Loading events for user: $userId');
|
print(
|
||||||
|
'Loading events for user: $userId (canViewAllEvents: $canViewAllEvents)');
|
||||||
// Récupérer uniquement les événements où l'utilisateur est dans la workforce
|
QuerySnapshot eventsSnapshot;
|
||||||
final eventsSnapshot = await _firestore
|
// On charge tous les events pour les users non-admins aussi
|
||||||
.collection('events')
|
eventsSnapshot = await _firestore.collection('events').get();
|
||||||
.where('workforce', arrayContains: userId)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
print('Found ${eventsSnapshot.docs.length} events for user');
|
print('Found ${eventsSnapshot.docs.length} events for user');
|
||||||
|
|
||||||
_events = eventsSnapshot.docs.map((doc) {
|
// On filtre côté client si l'utilisateur n'est pas admin
|
||||||
|
final allEvents = eventsSnapshot.docs.map((doc) {
|
||||||
print('Event data: ${doc.data()}');
|
print('Event data: ${doc.data()}');
|
||||||
return EventModel.fromMap(doc.data(), doc.id);
|
return EventModel.fromMap(doc.data() as Map<String, dynamic>, doc.id);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
if (canViewAllEvents) {
|
||||||
|
_events = allEvents;
|
||||||
|
} else {
|
||||||
|
final userRef = _firestore.collection('users').doc(userId);
|
||||||
|
_events = allEvents
|
||||||
|
.where((e) => e.workforce.any((ref) => ref.id == userRef.id))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
print('Parsed ${_events.length} events');
|
print('Parsed ${_events.length} events');
|
||||||
|
|
||||||
|
@ -3,10 +3,12 @@ import 'package:firebase_auth/firebase_auth.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import '../models/user_model.dart';
|
import '../models/user_model.dart';
|
||||||
|
import '../models/role_model.dart';
|
||||||
import '../utils/firebase_storage_manager.dart';
|
import '../utils/firebase_storage_manager.dart';
|
||||||
|
|
||||||
class LocalUserProvider with ChangeNotifier {
|
class LocalUserProvider with ChangeNotifier {
|
||||||
UserModel? _currentUser;
|
UserModel? _currentUser;
|
||||||
|
RoleModel? _currentRole;
|
||||||
final FirebaseAuth _auth = FirebaseAuth.instance;
|
final FirebaseAuth _auth = FirebaseAuth.instance;
|
||||||
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
|
||||||
final FirebaseStorageManager _storageManager = FirebaseStorageManager();
|
final FirebaseStorageManager _storageManager = FirebaseStorageManager();
|
||||||
@ -19,6 +21,8 @@ class LocalUserProvider with ChangeNotifier {
|
|||||||
String? get profilePhotoUrl => _currentUser?.profilePhotoUrl;
|
String? get profilePhotoUrl => _currentUser?.profilePhotoUrl;
|
||||||
String? get email => _currentUser?.email;
|
String? get email => _currentUser?.email;
|
||||||
String? get phoneNumber => _currentUser?.phoneNumber;
|
String? get phoneNumber => _currentUser?.phoneNumber;
|
||||||
|
RoleModel? get currentRole => _currentRole;
|
||||||
|
List<String> get permissions => _currentRole?.permissions ?? [];
|
||||||
|
|
||||||
/// Charge les données de l'utilisateur actuel
|
/// Charge les données de l'utilisateur actuel
|
||||||
Future<void> loadUserData() async {
|
Future<void> loadUserData() async {
|
||||||
@ -47,6 +51,7 @@ class LocalUserProvider with ChangeNotifier {
|
|||||||
|
|
||||||
setUser(UserModel.fromMap(userData, userDoc.id));
|
setUser(UserModel.fromMap(userData, userDoc.id));
|
||||||
print('User data loaded successfully');
|
print('User data loaded successfully');
|
||||||
|
await loadRole();
|
||||||
} else {
|
} else {
|
||||||
print('No user document found in Firestore');
|
print('No user document found in Firestore');
|
||||||
// Créer un document utilisateur par défaut
|
// Créer un document utilisateur par défaut
|
||||||
@ -73,6 +78,7 @@ class LocalUserProvider with ChangeNotifier {
|
|||||||
|
|
||||||
setUser(defaultUser);
|
setUser(defaultUser);
|
||||||
print('Default user document created');
|
print('Default user document created');
|
||||||
|
await loadRole();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error loading user data: $e');
|
print('Error loading user data: $e');
|
||||||
@ -154,4 +160,24 @@ class LocalUserProvider with ChangeNotifier {
|
|||||||
await _auth.signOut();
|
await _auth.signOut();
|
||||||
clearUser();
|
clearUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> loadRole() async {
|
||||||
|
if (_currentUser == null) return;
|
||||||
|
final roleId = _currentUser!.role;
|
||||||
|
if (roleId.isEmpty) return;
|
||||||
|
try {
|
||||||
|
final doc = await _firestore.collection('roles').doc(roleId).get();
|
||||||
|
if (doc.exists) {
|
||||||
|
_currentRole =
|
||||||
|
RoleModel.fromMap(doc.data() as Map<String, dynamic>, doc.id);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
print('Error loading role: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasPermission(String permission) {
|
||||||
|
return _currentRole?.permissions.contains(permission) ?? false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ import '../services/user_service.dart';
|
|||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart';
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
|
|
||||||
class UsersProvider with ChangeNotifier {
|
class UsersProvider with ChangeNotifier {
|
||||||
final UserService _userService;
|
final UserService _userService;
|
||||||
@ -36,14 +38,16 @@ class UsersProvider with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Mise à jour d'un utilisateur
|
/// Mise à jour d'un utilisateur
|
||||||
Future<void> updateUser(UserModel user) async {
|
Future<void> updateUser(UserModel user, {String? roleId}) async {
|
||||||
try {
|
try {
|
||||||
await _firestore.collection('users').doc(user.uid).update({
|
await _firestore.collection('users').doc(user.uid).update({
|
||||||
'firstName': user.firstName,
|
'firstName': user.firstName,
|
||||||
'lastName': user.lastName,
|
'lastName': user.lastName,
|
||||||
'email': user.email,
|
'email': user.email,
|
||||||
'phoneNumber': user.phoneNumber,
|
'phoneNumber': user.phoneNumber,
|
||||||
'role': user.role,
|
'role': roleId != null
|
||||||
|
? _firestore.collection('roles').doc(roleId)
|
||||||
|
: user.role,
|
||||||
'profilePhotoUrl': user.profilePhotoUrl,
|
'profilePhotoUrl': user.profilePhotoUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,7 +79,8 @@ class UsersProvider with ChangeNotifier {
|
|||||||
await _userService.resetPassword(email);
|
await _userService.resetPassword(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createUserWithEmailInvite(UserModel user) async {
|
Future<void> createUserWithEmailInvite(BuildContext context, UserModel user,
|
||||||
|
{String? roleId}) async {
|
||||||
String? authUid;
|
String? authUid;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -87,14 +92,12 @@ class UsersProvider with ChangeNotifier {
|
|||||||
throw Exception('Aucun utilisateur connecté');
|
throw Exception('Aucun utilisateur connecté');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vérifier le rôle de l'utilisateur actuel
|
// Vérifier la permission via le provider
|
||||||
final currentUserDoc =
|
final localUserProvider =
|
||||||
await _firestore.collection('users').doc(currentUser.uid).get();
|
Provider.of<LocalUserProvider>(context, listen: false);
|
||||||
print('Current user role: ${currentUserDoc.data()?['role']}');
|
if (!localUserProvider.hasPermission('add_user')) {
|
||||||
|
|
||||||
if (currentUserDoc.data()?['role'] != 'ADMIN') {
|
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Seuls les administrateurs peuvent créer des utilisateurs');
|
'Vous n\'avez pas la permission de créer des utilisateurs');
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -114,7 +117,9 @@ class UsersProvider with ChangeNotifier {
|
|||||||
'lastName': user.lastName,
|
'lastName': user.lastName,
|
||||||
'email': user.email,
|
'email': user.email,
|
||||||
'phoneNumber': user.phoneNumber,
|
'phoneNumber': user.phoneNumber,
|
||||||
'role': user.role,
|
'role': roleId != null
|
||||||
|
? _firestore.collection('roles').doc(roleId)
|
||||||
|
: user.role,
|
||||||
'profilePhotoUrl': user.profilePhotoUrl,
|
'profilePhotoUrl': user.profilePhotoUrl,
|
||||||
'createdAt': FieldValue.serverTimestamp(),
|
'createdAt': FieldValue.serverTimestamp(),
|
||||||
});
|
});
|
||||||
@ -142,7 +147,7 @@ class UsersProvider with ChangeNotifier {
|
|||||||
lastName: user.lastName,
|
lastName: user.lastName,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
phoneNumber: user.phoneNumber,
|
phoneNumber: user.phoneNumber,
|
||||||
role: user.role,
|
role: roleId ?? user.role,
|
||||||
profilePhotoUrl: user.profilePhotoUrl,
|
profilePhotoUrl: user.profilePhotoUrl,
|
||||||
);
|
);
|
||||||
_users.add(newUser);
|
_users.add(newUser);
|
||||||
|
@ -5,13 +5,12 @@ import 'package:em2rp/views/login_page.dart';
|
|||||||
|
|
||||||
class AuthGuard extends StatelessWidget {
|
class AuthGuard extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final String?
|
final String? requiredPermission;
|
||||||
requiredRole; // Si non null, la page est réservée à ce rôle (ex: "ADMIN")
|
|
||||||
|
|
||||||
const AuthGuard({
|
const AuthGuard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
this.requiredRole,
|
this.requiredPermission,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -20,13 +19,12 @@ class AuthGuard extends StatelessWidget {
|
|||||||
|
|
||||||
// Si l'utilisateur n'est pas connecté
|
// Si l'utilisateur n'est pas connecté
|
||||||
if (localAuthProvider.currentUser == null) {
|
if (localAuthProvider.currentUser == null) {
|
||||||
// Retourne la page de connexion.
|
|
||||||
// Vous pouvez aussi déclencher une redirection automatique si nécessaire.
|
|
||||||
return const LoginPage();
|
return const LoginPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si la page requiert un rôle spécifique et que l'utilisateur ne le possède pas
|
// Si la page requiert une permission spécifique et que l'utilisateur ne la possède pas
|
||||||
if (requiredRole != null && localAuthProvider.role != requiredRole) {
|
if (requiredPermission != null &&
|
||||||
|
!localAuthProvider.hasPermission(requiredPermission!)) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text("Accès refusé")),
|
appBar: AppBar(title: const Text("Accès refusé")),
|
||||||
body: const Center(
|
body: const Center(
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
class Constants {
|
|
||||||
static const List<String> userRoles = ['USER', 'ADMIN'];
|
|
||||||
}
|
|
@ -1,5 +1,3 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart'; // pour kIsWeb
|
import 'package:flutter/foundation.dart'; // pour kIsWeb
|
||||||
import 'package:firebase_storage/firebase_storage.dart';
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
@ -47,8 +45,9 @@ class FirebaseStorageManager {
|
|||||||
uploadTask = storageRef.putData(bytes);
|
uploadTask = storageRef.putData(bytes);
|
||||||
} else {
|
} else {
|
||||||
// Pour mobile/desktop, utiliser un File (dart:io)
|
// Pour mobile/desktop, utiliser un File (dart:io)
|
||||||
final file = File(imageFile.path);
|
// Sur mobile, image_picker fournit un path, mais on ne doit pas utiliser File sur le web
|
||||||
uploadTask = storageRef.putFile(file);
|
final bytes = await imageFile.readAsBytes();
|
||||||
|
uploadTask = storageRef.putData(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
final TaskSnapshot snapshot = await uploadTask.whenComplete(() {});
|
final TaskSnapshot snapshot = await uploadTask.whenComplete(() {});
|
||||||
|
@ -5,7 +5,7 @@ import 'package:em2rp/providers/local_user_provider.dart';
|
|||||||
|
|
||||||
class PermissionGate extends StatelessWidget {
|
class PermissionGate extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final List<Permission> requiredPermissions;
|
final List<String> requiredPermissions;
|
||||||
final bool requireAll;
|
final bool requireAll;
|
||||||
final Widget? fallback;
|
final Widget? fallback;
|
||||||
|
|
||||||
@ -26,10 +26,9 @@ class PermissionGate extends StatelessWidget {
|
|||||||
return fallback ?? const SizedBox.shrink();
|
return fallback ?? const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
final userRole = Roles.fromString(currentUser.role);
|
|
||||||
final hasPermission = requireAll
|
final hasPermission = requireAll
|
||||||
? userRole.hasAllPermissions(requiredPermissions)
|
? hasAllPermissions(localUserProvider, requiredPermissions)
|
||||||
: userRole.hasAnyPermission(requiredPermissions);
|
: hasAnyPermission(localUserProvider, requiredPermissions);
|
||||||
|
|
||||||
if (hasPermission) {
|
if (hasPermission) {
|
||||||
return child;
|
return child;
|
||||||
@ -39,4 +38,18 @@ class PermissionGate extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasAllPermissions(LocalUserProvider provider, List<String> permissions) {
|
||||||
|
for (final perm in permissions) {
|
||||||
|
if (!provider.hasPermission(perm)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAnyPermission(LocalUserProvider provider, List<String> permissions) {
|
||||||
|
for (final perm in permissions) {
|
||||||
|
if (provider.hasPermission(perm)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,32 +27,36 @@ class LoginViewModel extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
print('User signed in');
|
// --- Étape 1: Connecter l'utilisateur dans Firebase Auth ---
|
||||||
|
// Appelle la méthode du provider qui gère la connexion Auth ET le chargement des données utilisateur
|
||||||
// Attendre que les données utilisateur soient chargées
|
await localAuthProvider.signInWithEmailAndPassword(
|
||||||
await localAuthProvider.loadUserData();
|
emailController.text,
|
||||||
|
passwordController.text,
|
||||||
|
);
|
||||||
// Vérifier si le contexte est toujours valide
|
// Vérifier si le contexte est toujours valide
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
// Vérifier si l'utilisateur a bien été chargé
|
// Vérifier si l'utilisateur a bien été chargé dans le provider
|
||||||
if (localAuthProvider.currentUser != null) {
|
if (localAuthProvider.currentUser != null) {
|
||||||
// Utiliser pushReplacementNamed pour une transition propre
|
// Utiliser pushReplacementNamed pour une transition propre
|
||||||
Navigator.of(context, rootNavigator: true)
|
Navigator.of(context, rootNavigator: true)
|
||||||
.pushReplacementNamed('/calendar');
|
.pushReplacementNamed('/calendar');
|
||||||
} else {
|
} else {
|
||||||
errorMessage = 'Erreur lors du chargement des données utilisateur';
|
errorMessage =
|
||||||
|
'Erreur inattendue après connexion: Données utilisateur non chargées.';
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} on FirebaseAuthException catch (e) {
|
} on FirebaseAuthException catch (e) {
|
||||||
|
// Gestion spécifique des erreurs d'authentification (email/mot de passe incorrects, etc.)
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
errorMessage =
|
errorMessage =
|
||||||
e.message ?? 'Une erreur est survenue lors de la connexion';
|
e.message ?? 'Une erreur est survenue lors de la connexion Firebase.';
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// Gestion des autres erreurs potentielles (ex: erreur lors de loadUserData)
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
errorMessage = 'Une erreur inattendue est survenue';
|
errorMessage = 'Une erreur inattendue est survenue: ${e.toString()}';
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import 'package:em2rp/providers/local_user_provider.dart';
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
import 'package:em2rp/providers/event_provider.dart';
|
import 'package:em2rp/providers/event_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:em2rp/widgets/custom_app_bar.dart';
|
import 'package:em2rp/views/widgets/custom_app_bar.dart';
|
||||||
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
import 'package:em2rp/views/widgets/nav/main_drawer.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:table_calendar/table_calendar.dart';
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
import 'package:em2rp/models/event_model.dart';
|
import 'package:em2rp/models/event_model.dart';
|
||||||
import 'package:em2rp/widgets/event_details.dart';
|
import 'package:em2rp/views/widgets/calendar_widgets/event_details.dart';
|
||||||
import 'package:intl/date_symbol_data_local.dart';
|
import 'package:intl/date_symbol_data_local.dart';
|
||||||
import 'package:em2rp/views/widgets/calendar_widgets/month_view.dart';
|
import 'package:em2rp/views/widgets/calendar_widgets/month_view.dart';
|
||||||
import 'package:em2rp/views/widgets/calendar_widgets/week_view.dart';
|
import 'package:em2rp/views/widgets/calendar_widgets/week_view.dart';
|
||||||
|
import 'package:em2rp/views/event_add_page.dart';
|
||||||
|
import 'package:em2rp/views/widgets/calendar_widgets/mobile_calendar_view.dart';
|
||||||
|
import 'package:em2rp/utils/colors.dart';
|
||||||
|
|
||||||
class CalendarPage extends StatefulWidget {
|
class CalendarPage extends StatefulWidget {
|
||||||
const CalendarPage({super.key});
|
const CalendarPage({super.key});
|
||||||
@ -23,12 +26,60 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
DateTime _focusedDay = DateTime.now();
|
DateTime _focusedDay = DateTime.now();
|
||||||
DateTime? _selectedDay;
|
DateTime? _selectedDay;
|
||||||
EventModel? _selectedEvent;
|
EventModel? _selectedEvent;
|
||||||
|
bool _calendarCollapsed = false;
|
||||||
|
int _selectedEventIndex = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
initializeDateFormatting('fr_FR', null);
|
initializeDateFormatting('fr_FR', null);
|
||||||
Future.microtask(() => _loadEvents());
|
Future.microtask(() => _loadEvents());
|
||||||
|
// Sélection automatique de l'événement le plus proche de maintenant
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
final eventProvider = Provider.of<EventProvider>(context, listen: false);
|
||||||
|
final events = eventProvider.events;
|
||||||
|
if (events.isNotEmpty) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
// Pour mobile : sélectionner le premier événement du jour ou le prochain événement à venir
|
||||||
|
final todayEvents = events
|
||||||
|
.where((e) =>
|
||||||
|
e.startDateTime.year == now.year &&
|
||||||
|
e.startDateTime.month == now.month &&
|
||||||
|
e.startDateTime.day == now.day)
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
|
EventModel? selected;
|
||||||
|
DateTime? selectedDay;
|
||||||
|
int selectedEventIndex = 0;
|
||||||
|
if (todayEvents.isNotEmpty) {
|
||||||
|
selected = todayEvents[0];
|
||||||
|
selectedDay = DateTime(now.year, now.month, now.day);
|
||||||
|
} else {
|
||||||
|
// Chercher le prochain événement à venir
|
||||||
|
final futureEvents = events
|
||||||
|
.where((e) => e.startDateTime.isAfter(now))
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
|
if (futureEvents.isNotEmpty) {
|
||||||
|
selected = futureEvents[0];
|
||||||
|
selectedDay = DateTime(selected.startDateTime.year,
|
||||||
|
selected.startDateTime.month, selected.startDateTime.day);
|
||||||
|
} else {
|
||||||
|
// Aucun événement à venir, prendre le plus proche dans le passé
|
||||||
|
events.sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
|
selected = events.last;
|
||||||
|
selectedDay = DateTime(selected.startDateTime.year,
|
||||||
|
selected.startDateTime.month, selected.startDateTime.day);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_selectedDay = selectedDay;
|
||||||
|
_focusedDay = selectedDay!;
|
||||||
|
_selectedEventIndex = 0;
|
||||||
|
_selectedEvent = selected;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadEvents() async {
|
Future<void> _loadEvents() async {
|
||||||
@ -36,9 +87,13 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
Provider.of<LocalUserProvider>(context, listen: false);
|
Provider.of<LocalUserProvider>(context, listen: false);
|
||||||
final eventProvider = Provider.of<EventProvider>(context, listen: false);
|
final eventProvider = Provider.of<EventProvider>(context, listen: false);
|
||||||
final userId = localAuthProvider.uid;
|
final userId = localAuthProvider.uid;
|
||||||
|
print('Permissions utilisateur: ${localAuthProvider.permissions}');
|
||||||
|
final canViewAllEvents = localAuthProvider.hasPermission('view_all_events');
|
||||||
|
print('canViewAllEvents: $canViewAllEvents');
|
||||||
|
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
await eventProvider.loadUserEvents(userId);
|
await eventProvider.loadUserEvents(userId,
|
||||||
|
canViewAllEvents: canViewAllEvents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +106,8 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final eventProvider = Provider.of<EventProvider>(context);
|
final eventProvider = Provider.of<EventProvider>(context);
|
||||||
|
final localUserProvider = Provider.of<LocalUserProvider>(context);
|
||||||
|
final isAdmin = localUserProvider.hasPermission('view_all_users');
|
||||||
final isMobile = MediaQuery.of(context).size.width < 600;
|
final isMobile = MediaQuery.of(context).size.width < 600;
|
||||||
|
|
||||||
if (eventProvider.isLoading) {
|
if (eventProvider.isLoading) {
|
||||||
@ -62,11 +119,40 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: const CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: 'Calendrier',
|
title: _getMonthName(_focusedDay.month),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
_calendarCollapsed
|
||||||
|
? Icons.keyboard_arrow_down
|
||||||
|
: Icons.keyboard_arrow_up,
|
||||||
|
color: AppColors.blanc,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_calendarCollapsed = !_calendarCollapsed;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
drawer: const MainDrawer(currentPage: '/calendar'),
|
drawer: const MainDrawer(currentPage: '/calendar'),
|
||||||
body: isMobile ? _buildMobileLayout() : _buildDesktopLayout(),
|
body: isMobile ? _buildMobileLayout() : _buildDesktopLayout(),
|
||||||
|
floatingActionButton: isAdmin
|
||||||
|
? FloatingActionButton(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => const EventAddEditPage(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.add, color: Colors.red),
|
||||||
|
tooltip: 'Ajouter un événement',
|
||||||
|
)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +180,11 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
: const Center(
|
: Center(
|
||||||
child:
|
child: _selectedDay != null
|
||||||
Text('Sélectionnez un événement pour voir les détails'),
|
? Text('Aucun événement ne démarre à cette date')
|
||||||
|
: const Text(
|
||||||
|
'Sélectionnez un événement pour voir les détails'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -105,31 +193,331 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
|
|
||||||
Widget _buildMobileLayout() {
|
Widget _buildMobileLayout() {
|
||||||
final eventProvider = Provider.of<EventProvider>(context);
|
final eventProvider = Provider.of<EventProvider>(context);
|
||||||
return Column(
|
final eventsForSelectedDay = _selectedDay == null
|
||||||
children: [
|
? []
|
||||||
// Calendrier
|
: eventProvider.events
|
||||||
Expanded(
|
.where((e) =>
|
||||||
child: _buildCalendar(),
|
e.startDateTime.year == _selectedDay!.year &&
|
||||||
),
|
e.startDateTime.month == _selectedDay!.month &&
|
||||||
// Détails de l'événement
|
e.startDateTime.day == _selectedDay!.day)
|
||||||
if (_selectedEvent != null)
|
.toList()
|
||||||
Expanded(
|
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
child: EventDetails(
|
final hasEvents = eventsForSelectedDay.isNotEmpty;
|
||||||
event: _selectedEvent!,
|
final currentEvent =
|
||||||
selectedDate: _selectedDay,
|
hasEvents && _selectedEventIndex < eventsForSelectedDay.length
|
||||||
events: eventProvider.events,
|
? eventsForSelectedDay[_selectedEventIndex]
|
||||||
onSelectEvent: (event, date) {
|
: null;
|
||||||
setState(() {
|
|
||||||
_selectedEvent = event;
|
// GESTURE DETECTOR pour swipe vertical (plier/déplier) et horizontal (mois)
|
||||||
_selectedDay = date;
|
return GestureDetector(
|
||||||
});
|
onVerticalDragEnd: (details) {
|
||||||
},
|
if (details.primaryVelocity != null) {
|
||||||
|
if (details.primaryVelocity! < -200) {
|
||||||
|
// Swipe vers le haut : plier
|
||||||
|
setState(() {
|
||||||
|
_calendarCollapsed = true;
|
||||||
|
});
|
||||||
|
} else if (details.primaryVelocity! > 200) {
|
||||||
|
// Swipe vers le bas : déplier
|
||||||
|
setState(() {
|
||||||
|
_calendarCollapsed = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onHorizontalDragEnd: (details) {
|
||||||
|
if (details.primaryVelocity != null) {
|
||||||
|
if (details.primaryVelocity! < -200) {
|
||||||
|
// Swipe gauche : mois suivant
|
||||||
|
setState(() {
|
||||||
|
_focusedDay =
|
||||||
|
DateTime(_focusedDay.year, _focusedDay.month + 1, 1);
|
||||||
|
});
|
||||||
|
} else if (details.primaryVelocity! > 200) {
|
||||||
|
// Swipe droite : mois précédent
|
||||||
|
setState(() {
|
||||||
|
_focusedDay =
|
||||||
|
DateTime(_focusedDay.year, _focusedDay.month - 1, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
// Calendrier + détails en dessous
|
||||||
|
AnimatedPositioned(
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
top: _calendarCollapsed ? -600 : 0, // cache le calendrier en haut
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
height: _calendarCollapsed ? 0 : null,
|
||||||
|
child: Container(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildMonthHeader(context),
|
||||||
|
if (!_calendarCollapsed)
|
||||||
|
// Ajout d'un GestureDetector pour swipe horizontal sur le calendrier
|
||||||
|
GestureDetector(
|
||||||
|
onHorizontalDragEnd: (details) {
|
||||||
|
if (details.primaryVelocity != null) {
|
||||||
|
if (details.primaryVelocity! < -200) {
|
||||||
|
// Swipe gauche : mois suivant
|
||||||
|
setState(() {
|
||||||
|
_focusedDay = DateTime(
|
||||||
|
_focusedDay.year, _focusedDay.month + 1, 1);
|
||||||
|
});
|
||||||
|
} else if (details.primaryVelocity! > 200) {
|
||||||
|
// Swipe droite : mois précédent
|
||||||
|
setState(() {
|
||||||
|
_focusedDay = DateTime(
|
||||||
|
_focusedDay.year, _focusedDay.month - 1, 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: MobileCalendarView(
|
||||||
|
focusedDay: _focusedDay,
|
||||||
|
selectedDay: _selectedDay,
|
||||||
|
events: eventProvider.events,
|
||||||
|
onDaySelected: (day) {
|
||||||
|
final eventsForDay = eventProvider.events
|
||||||
|
.where((e) =>
|
||||||
|
e.startDateTime.year == day.year &&
|
||||||
|
e.startDateTime.month == day.month &&
|
||||||
|
e.startDateTime.day == day.day)
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) =>
|
||||||
|
a.startDateTime.compareTo(b.startDateTime));
|
||||||
|
setState(() {
|
||||||
|
_selectedDay = day;
|
||||||
|
_calendarCollapsed = false;
|
||||||
|
_selectedEventIndex = 0;
|
||||||
|
_selectedEvent = eventsForDay.isNotEmpty
|
||||||
|
? eventsForDay[0]
|
||||||
|
: null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: hasEvents
|
||||||
|
// Ajout d'un GestureDetector pour swipe horizontal sur le détail événement
|
||||||
|
? GestureDetector(
|
||||||
|
onHorizontalDragEnd: (details) {
|
||||||
|
if (details.primaryVelocity != null) {
|
||||||
|
if (details.primaryVelocity! < -200) {
|
||||||
|
// Swipe gauche : événement suivant
|
||||||
|
if (_selectedEventIndex <
|
||||||
|
eventsForSelectedDay.length - 1) {
|
||||||
|
setState(() {
|
||||||
|
_selectedEventIndex++;
|
||||||
|
_selectedEvent = eventsForSelectedDay[
|
||||||
|
_selectedEventIndex];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (details.primaryVelocity! > 200) {
|
||||||
|
// Swipe droite : événement précédent
|
||||||
|
if (_selectedEventIndex > 0) {
|
||||||
|
setState(() {
|
||||||
|
_selectedEventIndex--;
|
||||||
|
_selectedEvent = eventsForSelectedDay[
|
||||||
|
_selectedEventIndex];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: EventDetails(
|
||||||
|
event: eventsForSelectedDay[_selectedEventIndex],
|
||||||
|
selectedDate: _selectedDay,
|
||||||
|
events: eventsForSelectedDay.cast<EventModel>(),
|
||||||
|
onSelectEvent: (event, date) {
|
||||||
|
final idx = eventsForSelectedDay
|
||||||
|
.indexWhere((e) => e.id == event.id);
|
||||||
|
setState(() {
|
||||||
|
_selectedEventIndex = idx >= 0 ? idx : 0;
|
||||||
|
_selectedEvent = event;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Center(
|
||||||
|
child: Text(
|
||||||
|
'Aucun événement ne démarre à cette date')),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
// Vue détail (prend tout l'espace quand calendrier caché)
|
||||||
|
if (_calendarCollapsed && _selectedDay != null)
|
||||||
|
AnimatedPositioned(
|
||||||
|
duration: const Duration(milliseconds: 400),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
top: _calendarCollapsed ? 0 : 600,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
child: Container(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildMonthHeader(context),
|
||||||
|
Expanded(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
if (currentEvent != null)
|
||||||
|
// Ajout d'un GestureDetector pour swipe horizontal sur le détail événement
|
||||||
|
GestureDetector(
|
||||||
|
onHorizontalDragEnd: (details) {
|
||||||
|
if (details.primaryVelocity != null) {
|
||||||
|
if (details.primaryVelocity! < -200) {
|
||||||
|
// Swipe gauche : événement suivant
|
||||||
|
if (_selectedEventIndex <
|
||||||
|
eventsForSelectedDay.length - 1) {
|
||||||
|
setState(() {
|
||||||
|
_selectedEventIndex++;
|
||||||
|
_selectedEvent = eventsForSelectedDay[
|
||||||
|
_selectedEventIndex];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (details.primaryVelocity! > 200) {
|
||||||
|
// Swipe droite : événement précédent
|
||||||
|
if (_selectedEventIndex > 0) {
|
||||||
|
setState(() {
|
||||||
|
_selectedEventIndex--;
|
||||||
|
_selectedEvent = eventsForSelectedDay[
|
||||||
|
_selectedEventIndex];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: EventDetails(
|
||||||
|
event: currentEvent,
|
||||||
|
selectedDate: _selectedDay,
|
||||||
|
events: eventsForSelectedDay.cast<EventModel>(),
|
||||||
|
onSelectEvent: (event, date) {
|
||||||
|
final idx = eventsForSelectedDay
|
||||||
|
.indexWhere((e) => e.id == event.id);
|
||||||
|
setState(() {
|
||||||
|
_selectedEventIndex = idx >= 0 ? idx : 0;
|
||||||
|
_selectedEvent = event;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!hasEvents)
|
||||||
|
Center(
|
||||||
|
child: Text(
|
||||||
|
'Aucun événement ne démarre à cette date'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildMonthHeader(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8, bottom: 8),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.chevron_left,
|
||||||
|
color: AppColors.rouge, size: 28),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_focusedDay =
|
||||||
|
DateTime(_focusedDay.year, _focusedDay.month - 1, 1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_calendarCollapsed = !_calendarCollapsed;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
_getMonthName(_focusedDay.month),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: AppColors.rouge,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontSize: 20,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Icon(
|
||||||
|
_calendarCollapsed
|
||||||
|
? Icons.keyboard_arrow_down
|
||||||
|
: Icons.keyboard_arrow_up,
|
||||||
|
color: AppColors.rouge,
|
||||||
|
size: 26,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.chevron_right,
|
||||||
|
color: AppColors.rouge, size: 28),
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_focusedDay =
|
||||||
|
DateTime(_focusedDay.year, _focusedDay.month + 1, 1);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String _getMonthName(int month) {
|
||||||
|
switch (month) {
|
||||||
|
case 1:
|
||||||
|
return 'Janvier';
|
||||||
|
case 2:
|
||||||
|
return 'Février';
|
||||||
|
case 3:
|
||||||
|
return 'Mars';
|
||||||
|
case 4:
|
||||||
|
return 'Avril';
|
||||||
|
case 5:
|
||||||
|
return 'Mai';
|
||||||
|
case 6:
|
||||||
|
return 'Juin';
|
||||||
|
case 7:
|
||||||
|
return 'Juillet';
|
||||||
|
case 8:
|
||||||
|
return 'Août';
|
||||||
|
case 9:
|
||||||
|
return 'Septembre';
|
||||||
|
case 10:
|
||||||
|
return 'Octobre';
|
||||||
|
case 11:
|
||||||
|
return 'Novembre';
|
||||||
|
case 12:
|
||||||
|
return 'Décembre';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildCalendar() {
|
Widget _buildCalendar() {
|
||||||
final eventProvider = Provider.of<EventProvider>(context);
|
final eventProvider = Provider.of<EventProvider>(context);
|
||||||
|
|
||||||
@ -141,6 +529,7 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
onEventSelected: (event) {
|
onEventSelected: (event) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedEvent = event;
|
_selectedEvent = event;
|
||||||
|
_selectedDay = event.startDateTime;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onSwitchToMonth: () {
|
onSwitchToMonth: () {
|
||||||
@ -148,6 +537,33 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
_calendarFormat = CalendarFormat.month;
|
_calendarFormat = CalendarFormat.month;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
onDaySelected: (selectedDay) {
|
||||||
|
final eventsForDay = eventProvider.events
|
||||||
|
.where((e) =>
|
||||||
|
e.startDateTime.year == selectedDay.year &&
|
||||||
|
e.startDateTime.month == selectedDay.month &&
|
||||||
|
e.startDateTime.day == selectedDay.day)
|
||||||
|
.toList();
|
||||||
|
eventsForDay
|
||||||
|
.sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
|
setState(() {
|
||||||
|
_selectedDay = selectedDay;
|
||||||
|
if (eventsForDay.isNotEmpty) {
|
||||||
|
_selectedEvent = eventsForDay.first;
|
||||||
|
} else {
|
||||||
|
_selectedEvent = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (eventsForDay.isEmpty) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text("Aucun événement ne démarre à cette date."),
|
||||||
|
duration: Duration(seconds: 2),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedEvent: _selectedEvent,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return MonthView(
|
return MonthView(
|
||||||
@ -156,9 +572,21 @@ class _CalendarPageState extends State<CalendarPage> {
|
|||||||
calendarFormat: _calendarFormat,
|
calendarFormat: _calendarFormat,
|
||||||
events: eventProvider.events,
|
events: eventProvider.events,
|
||||||
onDaySelected: (selectedDay, focusedDay) {
|
onDaySelected: (selectedDay, focusedDay) {
|
||||||
|
final eventsForDay = eventProvider.events
|
||||||
|
.where((event) =>
|
||||||
|
event.startDateTime.year == selectedDay.year &&
|
||||||
|
event.startDateTime.month == selectedDay.month &&
|
||||||
|
event.startDateTime.day == selectedDay.day)
|
||||||
|
.toList()
|
||||||
|
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDay = selectedDay;
|
_selectedDay = selectedDay;
|
||||||
_focusedDay = focusedDay;
|
_focusedDay = focusedDay;
|
||||||
|
if (eventsForDay.isNotEmpty) {
|
||||||
|
_selectedEvent = eventsForDay.first;
|
||||||
|
} else {
|
||||||
|
_selectedEvent = null;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onFormatChanged: (format) {
|
onFormatChanged: (format) {
|
||||||
|
849
em2rp/lib/views/event_add_page.dart
Normal file
849
em2rp/lib/views/event_add_page.dart
Normal file
@ -0,0 +1,849 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:em2rp/providers/event_provider.dart';
|
||||||
|
import 'package:em2rp/models/event_model.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:em2rp/views/widgets/inputs/int_stepper_field.dart';
|
||||||
|
import 'package:em2rp/models/user_model.dart';
|
||||||
|
import 'package:em2rp/views/widgets/image/profile_picture.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:firebase_auth/firebase_auth.dart';
|
||||||
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_dropzone/flutter_dropzone.dart';
|
||||||
|
import 'package:em2rp/views/widgets/inputs/dropzone_upload_widget.dart';
|
||||||
|
import 'package:em2rp/views/widgets/user_management/user_multi_select_widget.dart';
|
||||||
|
import 'package:em2rp/views/widgets/inputs/option_selector_widget.dart';
|
||||||
|
// ignore: avoid_web_libraries_in_flutter
|
||||||
|
import 'dart:html' as html;
|
||||||
|
|
||||||
|
class EventAddEditPage extends StatefulWidget {
|
||||||
|
final EventModel? event;
|
||||||
|
const EventAddEditPage({super.key, this.event});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<EventAddEditPage> createState() => _EventAddEditPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EventAddEditPageState extends State<EventAddEditPage> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final TextEditingController _nameController = TextEditingController();
|
||||||
|
final TextEditingController _descriptionController = TextEditingController();
|
||||||
|
final TextEditingController _basePriceController = TextEditingController();
|
||||||
|
final TextEditingController _installationController = TextEditingController();
|
||||||
|
final TextEditingController _disassemblyController = TextEditingController();
|
||||||
|
final TextEditingController _addressController = TextEditingController();
|
||||||
|
DateTime? _startDateTime;
|
||||||
|
DateTime? _endDateTime;
|
||||||
|
bool _isLoading = false;
|
||||||
|
String? _error;
|
||||||
|
String? _success;
|
||||||
|
String? _selectedEventType;
|
||||||
|
final List<String> _eventTypes = ['Bal', 'Mariage', 'Anniversaire'];
|
||||||
|
final Map<String, double> _eventTypeDefaultPrices = {
|
||||||
|
'Bal': 800.0,
|
||||||
|
'Mariage': 1500.0,
|
||||||
|
'Anniversaire': 500.0,
|
||||||
|
};
|
||||||
|
int _descriptionMaxLines = 3;
|
||||||
|
List<String> _selectedUserIds = [];
|
||||||
|
List<UserModel> _allUsers = [];
|
||||||
|
bool _isLoadingUsers = true;
|
||||||
|
List<Map<String, String>> _uploadedFiles = [];
|
||||||
|
DropzoneViewController? _dropzoneController;
|
||||||
|
bool _isDropzoneHighlighted = false;
|
||||||
|
List<Map<String, dynamic>> _selectedOptions = [];
|
||||||
|
bool _formChanged = false;
|
||||||
|
EventStatus _selectedStatus = EventStatus.waitingForApproval;
|
||||||
|
|
||||||
|
bool get isEditMode => widget.event != null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_descriptionController.addListener(_handleDescriptionChange);
|
||||||
|
_fetchUsers();
|
||||||
|
_nameController.addListener(_onAnyFieldChanged);
|
||||||
|
_basePriceController.addListener(_onAnyFieldChanged);
|
||||||
|
_installationController.addListener(_onAnyFieldChanged);
|
||||||
|
_disassemblyController.addListener(_onAnyFieldChanged);
|
||||||
|
_addressController.addListener(_onAnyFieldChanged);
|
||||||
|
_descriptionController.addListener(_onAnyFieldChanged);
|
||||||
|
_addBeforeUnloadListener();
|
||||||
|
if (isEditMode) {
|
||||||
|
final e = widget.event!;
|
||||||
|
_nameController.text = e.name;
|
||||||
|
_descriptionController.text = e.description;
|
||||||
|
_basePriceController.text = e.basePrice.toStringAsFixed(2);
|
||||||
|
_installationController.text = e.installationTime.toString();
|
||||||
|
_disassemblyController.text = e.disassemblyTime.toString();
|
||||||
|
_addressController.text = e.address;
|
||||||
|
_startDateTime = e.startDateTime;
|
||||||
|
_endDateTime = e.endDateTime;
|
||||||
|
_selectedEventType = e.eventTypeId.isNotEmpty ? e.eventTypeId : null;
|
||||||
|
_selectedUserIds = e.workforce.map((ref) => ref.id).toList();
|
||||||
|
_uploadedFiles = List<Map<String, String>>.from(e.documents);
|
||||||
|
_selectedOptions = List<Map<String, dynamic>>.from(e.options);
|
||||||
|
_selectedStatus = e.status;
|
||||||
|
} else {
|
||||||
|
_selectedStatus = EventStatus.waitingForApproval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleDescriptionChange() {
|
||||||
|
final lines = '\n'.allMatches(_descriptionController.text).length + 1;
|
||||||
|
setState(() {
|
||||||
|
_descriptionMaxLines = lines.clamp(3, 6);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onAnyFieldChanged() {
|
||||||
|
if (!_formChanged) {
|
||||||
|
setState(() {
|
||||||
|
_formChanged = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchUsers() async {
|
||||||
|
final snapshot = await FirebaseFirestore.instance.collection('users').get();
|
||||||
|
setState(() {
|
||||||
|
_allUsers = snapshot.docs
|
||||||
|
.map((doc) => UserModel.fromMap(doc.data(), doc.id))
|
||||||
|
.toList();
|
||||||
|
_isLoadingUsers = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onEventTypeChanged(String? newType) {
|
||||||
|
if (newType == _selectedEventType) return;
|
||||||
|
setState(() {
|
||||||
|
_selectedEventType = newType;
|
||||||
|
if (newType != null) {
|
||||||
|
// Appliquer le prix par défaut si champ vide ou si type changé
|
||||||
|
final defaultPrice = _eventTypeDefaultPrices[newType] ?? 0.0;
|
||||||
|
if (_basePriceController.text.isEmpty ||
|
||||||
|
(_selectedEventType != null &&
|
||||||
|
_basePriceController.text ==
|
||||||
|
(_eventTypeDefaultPrices[_selectedEventType] ?? '')
|
||||||
|
.toString())) {
|
||||||
|
_basePriceController.text = defaultPrice.toStringAsFixed(2);
|
||||||
|
}
|
||||||
|
// Efface les options non compatibles
|
||||||
|
final before = _selectedOptions.length;
|
||||||
|
_selectedOptions.removeWhere((opt) {
|
||||||
|
final types = opt['compatibleTypes'] as List<String>?;
|
||||||
|
if (types == null) return true;
|
||||||
|
return !types.contains(newType);
|
||||||
|
});
|
||||||
|
if (_selectedOptions.length < before && context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Certaines options ont été retirées car elles ne sont pas compatibles avec le type "$newType".')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_selectedOptions.clear();
|
||||||
|
}
|
||||||
|
_onAnyFieldChanged();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_nameController.dispose();
|
||||||
|
_descriptionController.dispose();
|
||||||
|
_basePriceController.dispose();
|
||||||
|
_installationController.dispose();
|
||||||
|
_disassemblyController.dispose();
|
||||||
|
_addressController.dispose();
|
||||||
|
_removeBeforeUnloadListener();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Web: beforeunload pour empêcher la fermeture sans confirmation ---
|
||||||
|
void _addBeforeUnloadListener() {
|
||||||
|
if (kIsWeb) {
|
||||||
|
html.window.onBeforeUnload.listen(_beforeUnloadHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _removeBeforeUnloadListener() {
|
||||||
|
if (kIsWeb) {
|
||||||
|
// Il n'est pas possible de retirer un listener anonyme, donc on ne fait rien ici.
|
||||||
|
// Pour une gestion plus fine, il faudrait stocker la référence du listener.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _beforeUnloadHandler(html.Event event) {
|
||||||
|
if (_formChanged) {
|
||||||
|
event.preventDefault();
|
||||||
|
// Pour Chrome/Edge/Firefox, il faut définir returnValue
|
||||||
|
// ignore: unsafe_html
|
||||||
|
(event as dynamic).returnValue = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _onWillPop() async {
|
||||||
|
if (!_formChanged) return true;
|
||||||
|
final shouldLeave = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text('Quitter la page ?'),
|
||||||
|
content: const Text(
|
||||||
|
'Les modifications non enregistrées seront perdues. Voulez-vous vraiment quitter ?'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(false),
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(true),
|
||||||
|
child: const Text('Quitter'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return shouldLeave ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _pickAndUploadFiles() async {
|
||||||
|
final result = await FilePicker.platform
|
||||||
|
.pickFiles(allowMultiple: true, withData: true);
|
||||||
|
if (result != null && result.files.isNotEmpty) {
|
||||||
|
setState(() => _isLoading = true);
|
||||||
|
try {
|
||||||
|
List<Map<String, String>> files = [];
|
||||||
|
for (final file in result.files) {
|
||||||
|
final fileBytes = file.bytes;
|
||||||
|
final fileName = file.name;
|
||||||
|
if (fileBytes != null) {
|
||||||
|
final ref = FirebaseStorage.instance.ref().child(
|
||||||
|
'events/temp/${DateTime.now().millisecondsSinceEpoch}_$fileName');
|
||||||
|
final uploadTask = await ref.putData(fileBytes);
|
||||||
|
final url = await uploadTask.ref.getDownloadURL();
|
||||||
|
files.add({'name': fileName, 'url': url});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_error = "Impossible de lire le fichier ${file.name}";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_uploadedFiles.addAll(files);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_error = 'Erreur lors de l\'upload : $e';
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setState(() => _isLoading = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> moveEventFileHttp({
|
||||||
|
required String sourcePath,
|
||||||
|
required String destinationPath,
|
||||||
|
}) async {
|
||||||
|
final url = Uri.parse(
|
||||||
|
'https://us-central1-em2rp-951dc.cloudfunctions.net/moveEventFileV2');
|
||||||
|
final user = FirebaseAuth.instance.currentUser;
|
||||||
|
final idToken = await user?.getIdToken();
|
||||||
|
final response = await http.post(
|
||||||
|
url,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
if (idToken != null) 'Authorization': 'Bearer $idToken',
|
||||||
|
},
|
||||||
|
body: jsonEncode({
|
||||||
|
'data': {
|
||||||
|
'sourcePath': sourcePath,
|
||||||
|
'destinationPath': destinationPath,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
final data = jsonDecode(response.body);
|
||||||
|
if (data['url'] != null) {
|
||||||
|
return data['url'] as String;
|
||||||
|
} else if (data['result'] != null && data['result']['url'] != null) {
|
||||||
|
return data['result']['url'] as String;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
print('Erreur Cloud Function: \\n${response.body}');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _submit() async {
|
||||||
|
if (!_formKey.currentState!.validate() ||
|
||||||
|
_startDateTime == null ||
|
||||||
|
_endDateTime == null ||
|
||||||
|
_selectedEventType == null ||
|
||||||
|
_addressController.text.isEmpty) return;
|
||||||
|
if (_endDateTime!.isBefore(_startDateTime!) ||
|
||||||
|
_endDateTime!.isAtSameMomentAs(_startDateTime!)) {
|
||||||
|
setState(() {
|
||||||
|
_error = "La date de fin doit être postérieure à la date de début.";
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
_error = null;
|
||||||
|
_success = null;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final eventProvider = Provider.of<EventProvider>(context, listen: false);
|
||||||
|
if (isEditMode) {
|
||||||
|
// Edition : on met à jour l'événement existant
|
||||||
|
final updatedEvent = EventModel(
|
||||||
|
id: widget.event!.id,
|
||||||
|
name: _nameController.text.trim(),
|
||||||
|
description: _descriptionController.text.trim(),
|
||||||
|
startDateTime: _startDateTime!,
|
||||||
|
endDateTime: _endDateTime!,
|
||||||
|
basePrice: double.tryParse(_basePriceController.text) ?? 0.0,
|
||||||
|
installationTime: int.tryParse(_installationController.text) ?? 0,
|
||||||
|
disassemblyTime: int.tryParse(_disassemblyController.text) ?? 0,
|
||||||
|
eventTypeId: _selectedEventType!,
|
||||||
|
customerId: '',
|
||||||
|
address: _addressController.text.trim(),
|
||||||
|
workforce: _selectedUserIds
|
||||||
|
.map((id) =>
|
||||||
|
FirebaseFirestore.instance.collection('users').doc(id))
|
||||||
|
.toList(),
|
||||||
|
latitude: 0.0,
|
||||||
|
longitude: 0.0,
|
||||||
|
documents: _uploadedFiles,
|
||||||
|
options: _selectedOptions
|
||||||
|
.map((opt) => {
|
||||||
|
'name': opt['name'],
|
||||||
|
'price': opt['price'],
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
status: _selectedStatus,
|
||||||
|
);
|
||||||
|
final docRef = FirebaseFirestore.instance
|
||||||
|
.collection('events')
|
||||||
|
.doc(widget.event!.id);
|
||||||
|
await docRef.update(updatedEvent.toMap());
|
||||||
|
// Gestion des fichiers (si besoin, à adapter selon ta logique)
|
||||||
|
// ...
|
||||||
|
setState(() {
|
||||||
|
_success = "Événement modifié avec succès !";
|
||||||
|
});
|
||||||
|
if (context.mounted) Navigator.of(context).pop();
|
||||||
|
} else {
|
||||||
|
// Création : logique existante
|
||||||
|
final newEvent = EventModel(
|
||||||
|
id: '',
|
||||||
|
name: _nameController.text.trim(),
|
||||||
|
description: _descriptionController.text.trim(),
|
||||||
|
startDateTime: _startDateTime!,
|
||||||
|
endDateTime: _endDateTime!,
|
||||||
|
basePrice: double.tryParse(_basePriceController.text) ?? 0.0,
|
||||||
|
installationTime: int.tryParse(_installationController.text) ?? 0,
|
||||||
|
disassemblyTime: int.tryParse(_disassemblyController.text) ?? 0,
|
||||||
|
eventTypeId: _selectedEventType!,
|
||||||
|
customerId: '',
|
||||||
|
address: _addressController.text.trim(),
|
||||||
|
workforce: _selectedUserIds
|
||||||
|
.map((id) =>
|
||||||
|
FirebaseFirestore.instance.collection('users').doc(id))
|
||||||
|
.toList(),
|
||||||
|
latitude: 0.0,
|
||||||
|
longitude: 0.0,
|
||||||
|
documents: _uploadedFiles,
|
||||||
|
options: _selectedOptions
|
||||||
|
.map((opt) => {
|
||||||
|
'name': opt['name'],
|
||||||
|
'price': opt['price'],
|
||||||
|
})
|
||||||
|
.toList(),
|
||||||
|
status: _selectedStatus,
|
||||||
|
);
|
||||||
|
final docRef = await FirebaseFirestore.instance
|
||||||
|
.collection('events')
|
||||||
|
.add(newEvent.toMap());
|
||||||
|
final eventId = docRef.id;
|
||||||
|
List<Map<String, String>> newFiles = [];
|
||||||
|
for (final file in _uploadedFiles) {
|
||||||
|
final fileName = file['name']!;
|
||||||
|
final oldUrl = file['url']!;
|
||||||
|
String sourcePath;
|
||||||
|
final tempPattern = RegExp(r'events/temp/[^?]+');
|
||||||
|
final match = tempPattern.firstMatch(oldUrl);
|
||||||
|
if (match != null) {
|
||||||
|
sourcePath = match.group(0)!;
|
||||||
|
} else {
|
||||||
|
final tempFileName =
|
||||||
|
Uri.decodeComponent(oldUrl.split('/').last.split('?').first);
|
||||||
|
sourcePath = tempFileName;
|
||||||
|
}
|
||||||
|
final destinationPath = 'events/$eventId/$fileName';
|
||||||
|
final newUrl = await moveEventFileHttp(
|
||||||
|
sourcePath: sourcePath,
|
||||||
|
destinationPath: destinationPath,
|
||||||
|
);
|
||||||
|
if (newUrl != null) {
|
||||||
|
newFiles.add({'name': fileName, 'url': newUrl});
|
||||||
|
} else {
|
||||||
|
newFiles.add({'name': fileName, 'url': oldUrl});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await docRef.update({'documents': newFiles});
|
||||||
|
final localUserProvider =
|
||||||
|
Provider.of<LocalUserProvider>(context, listen: false);
|
||||||
|
final userId = localUserProvider.uid;
|
||||||
|
final canViewAllEvents =
|
||||||
|
localUserProvider.hasPermission('view_all_events');
|
||||||
|
if (userId != null) {
|
||||||
|
await eventProvider.loadUserEvents(userId,
|
||||||
|
canViewAllEvents: canViewAllEvents);
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_success = "Événement créé avec succès !";
|
||||||
|
});
|
||||||
|
if (context.mounted) Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_error = "Erreur lors de la sauvegarde : $e";
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildSectionTitle(String title) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 16.0, bottom: 8.0),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = Theme.of(context);
|
||||||
|
final isMobile = MediaQuery.of(context).size.width < 600;
|
||||||
|
return WillPopScope(
|
||||||
|
onWillPop: _onWillPop,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title:
|
||||||
|
Text(isEditMode ? 'Modifier un événement' : 'Créer un événement'),
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: (isMobile
|
||||||
|
? Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16, vertical: 12),
|
||||||
|
child: _buildFormContent(isMobile),
|
||||||
|
)
|
||||||
|
: Card(
|
||||||
|
elevation: 6,
|
||||||
|
margin: const EdgeInsets.all(24),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(18)),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 32, vertical: 32),
|
||||||
|
child: _buildFormContent(isMobile),
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildFormContent(bool isMobile) {
|
||||||
|
return Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 0.0, bottom: 4.0),
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Text(
|
||||||
|
'Informations principales',
|
||||||
|
style:
|
||||||
|
const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Nom de l\'événement',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
prefixIcon: Icon(Icons.event),
|
||||||
|
),
|
||||||
|
validator: (v) => v == null || v.isEmpty ? 'Champ requis' : null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
DropdownButtonFormField<String>(
|
||||||
|
value: _selectedEventType,
|
||||||
|
items: _eventTypes
|
||||||
|
.map((type) => DropdownMenuItem<String>(
|
||||||
|
value: type,
|
||||||
|
child: Text(type),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
onChanged: _onEventTypeChanged,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Type d\'événement',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
prefixIcon: Icon(Icons.category),
|
||||||
|
),
|
||||||
|
validator: (v) => v == null ? 'Sélectionnez un type' : null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
final picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime(2020),
|
||||||
|
lastDate: DateTime(2099),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final time = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (time != null) {
|
||||||
|
setState(() {
|
||||||
|
_startDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
time.hour,
|
||||||
|
time.minute,
|
||||||
|
);
|
||||||
|
if (_endDateTime != null &&
|
||||||
|
(_endDateTime!.isBefore(_startDateTime!) ||
|
||||||
|
_endDateTime!
|
||||||
|
.isAtSameMomentAs(_startDateTime!))) {
|
||||||
|
_endDateTime = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: AbsorbPointer(
|
||||||
|
child: TextFormField(
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Début',
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
prefixIcon: const Icon(Icons.calendar_today),
|
||||||
|
suffixIcon: const Icon(Icons.edit_calendar),
|
||||||
|
),
|
||||||
|
controller: TextEditingController(
|
||||||
|
text: _startDateTime == null
|
||||||
|
? ''
|
||||||
|
: DateFormat('dd/MM/yyyy HH:mm')
|
||||||
|
.format(_startDateTime!),
|
||||||
|
),
|
||||||
|
validator: (v) =>
|
||||||
|
_startDateTime == null ? 'Champ requis' : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: _startDateTime == null
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
final picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate:
|
||||||
|
_startDateTime!.add(const Duration(hours: 1)),
|
||||||
|
firstDate: _startDateTime!,
|
||||||
|
lastDate: DateTime(2099),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final time = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (time != null) {
|
||||||
|
setState(() {
|
||||||
|
_endDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
time.hour,
|
||||||
|
time.minute,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: AbsorbPointer(
|
||||||
|
child: TextFormField(
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Fin',
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
prefixIcon: const Icon(Icons.calendar_today),
|
||||||
|
suffixIcon: const Icon(Icons.edit_calendar),
|
||||||
|
),
|
||||||
|
controller: TextEditingController(
|
||||||
|
text: _endDateTime == null
|
||||||
|
? ''
|
||||||
|
: DateFormat('dd/MM/yyyy HH:mm')
|
||||||
|
.format(_endDateTime!),
|
||||||
|
),
|
||||||
|
validator: (v) => _endDateTime == null
|
||||||
|
? 'Champ requis'
|
||||||
|
: (_startDateTime != null &&
|
||||||
|
_endDateTime != null &&
|
||||||
|
(_endDateTime!.isBefore(_startDateTime!) ||
|
||||||
|
_endDateTime!
|
||||||
|
.isAtSameMomentAs(_startDateTime!)))
|
||||||
|
? 'La date de fin doit être après la date de début'
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextFormField(
|
||||||
|
controller: _basePriceController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Prix de base (€)',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
prefixIcon: Icon(Icons.euro),
|
||||||
|
hintText: '1050.50',
|
||||||
|
),
|
||||||
|
keyboardType: const TextInputType.numberWithOptions(decimal: true),
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp(r'^\d*\.?\d{0,2}')),
|
||||||
|
],
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return 'Le prix de base est requis';
|
||||||
|
}
|
||||||
|
final price = double.tryParse(value.replaceAll(',', '.'));
|
||||||
|
if (price == null) {
|
||||||
|
return 'Veuillez entrer un nombre valide';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
onChanged: (_) => _onAnyFieldChanged(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
OptionSelectorWidget(
|
||||||
|
eventType: _selectedEventType,
|
||||||
|
selectedOptions: _selectedOptions,
|
||||||
|
onChanged: (opts) => setState(() => _selectedOptions = opts),
|
||||||
|
onRemove: (name) {
|
||||||
|
setState(() {
|
||||||
|
_selectedOptions.removeWhere((o) => o['name'] == name);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
eventTypeRequired: _selectedEventType == null,
|
||||||
|
isMobile: isMobile,
|
||||||
|
),
|
||||||
|
_buildSectionTitle('Détails'),
|
||||||
|
AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
minHeight: 48,
|
||||||
|
maxHeight: isMobile ? 48.0 * 20 : 48.0 * 10,
|
||||||
|
),
|
||||||
|
child: TextFormField(
|
||||||
|
controller: _descriptionController,
|
||||||
|
minLines: 1,
|
||||||
|
maxLines: _descriptionMaxLines > (isMobile ? 20 : 10)
|
||||||
|
? (isMobile ? 20 : 10)
|
||||||
|
: _descriptionMaxLines,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Description',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
prefixIcon: Icon(Icons.description),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: IntStepperField(
|
||||||
|
label: 'Installation (h)',
|
||||||
|
controller: _installationController,
|
||||||
|
min: 0,
|
||||||
|
max: 99,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: IntStepperField(
|
||||||
|
label: 'Démontage (h)',
|
||||||
|
controller: _disassemblyController,
|
||||||
|
min: 0,
|
||||||
|
max: 99,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
_buildSectionTitle('Adresse'),
|
||||||
|
TextFormField(
|
||||||
|
controller: _addressController,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Adresse',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
prefixIcon: Icon(Icons.location_on),
|
||||||
|
),
|
||||||
|
validator: (v) => v == null || v.isEmpty ? 'Champ requis' : null,
|
||||||
|
),
|
||||||
|
_buildSectionTitle('Personnel'),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: UserMultiSelectWidget(
|
||||||
|
allUsers: _allUsers,
|
||||||
|
selectedUserIds: _selectedUserIds,
|
||||||
|
onChanged: (ids) => setState(() => _selectedUserIds = ids),
|
||||||
|
isLoading: _isLoadingUsers,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildSectionTitle('Documents'),
|
||||||
|
if (isMobile)
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.attach_file),
|
||||||
|
label: const Text('Ajouter un fichier'),
|
||||||
|
onPressed: _isLoading ? null : _pickAndUploadFiles,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
..._uploadedFiles.map((file) => ListTile(
|
||||||
|
dense: true,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
leading: const Icon(Icons.insert_drive_file),
|
||||||
|
title: Text(file['name'] ?? ''),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
onPressed: _isLoading
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
setState(() {
|
||||||
|
_uploadedFiles.remove(file);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
if (_error != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4.0),
|
||||||
|
child: Text(_error!,
|
||||||
|
style: const TextStyle(color: Colors.red)),
|
||||||
|
),
|
||||||
|
if (_success != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 4.0),
|
||||||
|
child: Text(_success!,
|
||||||
|
style: const TextStyle(color: Colors.green)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!isMobile)
|
||||||
|
DropzoneUploadWidget(
|
||||||
|
uploadedFiles: _uploadedFiles,
|
||||||
|
onFilesChanged: (files) =>
|
||||||
|
setState(() => _uploadedFiles = files),
|
||||||
|
isLoading: _isLoading,
|
||||||
|
error: _error,
|
||||||
|
success: _success,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: _isLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
final shouldLeave = await _onWillPop();
|
||||||
|
if (shouldLeave && context.mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.check),
|
||||||
|
onPressed: _isLoading ? null : _submit,
|
||||||
|
label: _isLoading
|
||||||
|
? const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
)
|
||||||
|
: Text(isEditMode ? 'Enregistrer' : 'Créer'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!isEditMode)
|
||||||
|
Center(
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.check_circle, color: Colors.white),
|
||||||
|
label: const Text('Définir cet événement comme confirmé'),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Colors.green,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
textStyle: const TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
onPressed: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:em2rp/views/widgets/inputs/styled_text_field.dart';
|
import 'package:em2rp/views/widgets/inputs/styled_text_field.dart';
|
||||||
import 'package:em2rp/views/widgets/image/profile_picture_selector.dart';
|
import 'package:em2rp/views/widgets/image/profile_picture_selector.dart';
|
||||||
import 'package:em2rp/widgets/custom_app_bar.dart';
|
import 'package:em2rp/views/widgets/custom_app_bar.dart';
|
||||||
|
|
||||||
class MyAccountPage extends StatelessWidget {
|
class MyAccountPage extends StatelessWidget {
|
||||||
const MyAccountPage({super.key});
|
const MyAccountPage({super.key});
|
||||||
|
@ -8,7 +8,8 @@ import 'package:em2rp/views/widgets/user_management/edit_user_dialog.dart';
|
|||||||
import 'package:em2rp/utils/colors.dart';
|
import 'package:em2rp/utils/colors.dart';
|
||||||
import 'package:em2rp/utils/permission_gate.dart';
|
import 'package:em2rp/utils/permission_gate.dart';
|
||||||
import 'package:em2rp/models/role_model.dart';
|
import 'package:em2rp/models/role_model.dart';
|
||||||
import 'package:em2rp/widgets/custom_app_bar.dart';
|
import 'package:em2rp/views/widgets/custom_app_bar.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
class UserManagementPage extends StatefulWidget {
|
class UserManagementPage extends StatefulWidget {
|
||||||
const UserManagementPage({super.key});
|
const UserManagementPage({super.key});
|
||||||
@ -31,7 +32,7 @@ class _UserManagementPageState extends State<UserManagementPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return PermissionGate(
|
return PermissionGate(
|
||||||
requiredPermissions: const [Permission.viewUsers],
|
requiredPermissions: const ['view_all_users'],
|
||||||
fallback: const Scaffold(
|
fallback: const Scaffold(
|
||||||
appBar: CustomAppBar(
|
appBar: CustomAppBar(
|
||||||
title: 'Accès refusé',
|
title: 'Accès refusé',
|
||||||
@ -110,7 +111,20 @@ class _UserManagementPageState extends State<UserManagementPage> {
|
|||||||
final lastNameController = TextEditingController();
|
final lastNameController = TextEditingController();
|
||||||
final emailController = TextEditingController();
|
final emailController = TextEditingController();
|
||||||
final phoneController = TextEditingController();
|
final phoneController = TextEditingController();
|
||||||
String selectedRole = Roles.values.first.name;
|
String? selectedRoleId;
|
||||||
|
List<RoleModel> availableRoles = [];
|
||||||
|
bool isLoadingRoles = true;
|
||||||
|
|
||||||
|
Future<void> _loadRoles() async {
|
||||||
|
final snapshot =
|
||||||
|
await FirebaseFirestore.instance.collection('roles').get();
|
||||||
|
availableRoles = snapshot.docs
|
||||||
|
.map((doc) => RoleModel.fromMap(doc.data(), doc.id))
|
||||||
|
.toList();
|
||||||
|
selectedRoleId =
|
||||||
|
availableRoles.isNotEmpty ? availableRoles.first.id : null;
|
||||||
|
isLoadingRoles = false;
|
||||||
|
}
|
||||||
|
|
||||||
InputDecoration buildInputDecoration(String label, IconData icon) {
|
InputDecoration buildInputDecoration(String label, IconData icon) {
|
||||||
return InputDecoration(
|
return InputDecoration(
|
||||||
@ -130,164 +144,162 @@ class _UserManagementPageState extends State<UserManagementPage> {
|
|||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => Dialog(
|
builder: (context) => FutureBuilder(
|
||||||
shape: RoundedRectangleBorder(
|
future: _loadRoles(),
|
||||||
borderRadius: BorderRadius.circular(16),
|
builder: (context, snapshot) {
|
||||||
),
|
return Dialog(
|
||||||
child: Container(
|
shape: RoundedRectangleBorder(
|
||||||
width: 400,
|
borderRadius: BorderRadius.circular(16),
|
||||||
padding: const EdgeInsets.all(24),
|
),
|
||||||
child: Column(
|
child: Container(
|
||||||
mainAxisSize: MainAxisSize.min,
|
width: 400,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
padding: const EdgeInsets.all(24),
|
||||||
children: [
|
child: Column(
|
||||||
Row(
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.person_add, color: AppColors.rouge),
|
Row(
|
||||||
const SizedBox(width: 12),
|
children: [
|
||||||
Text(
|
const Icon(Icons.person_add, color: AppColors.rouge),
|
||||||
'Nouvel utilisateur',
|
const SizedBox(width: 12),
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
Text(
|
||||||
color: AppColors.noir,
|
'Nouvel utilisateur',
|
||||||
fontWeight: FontWeight.bold,
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
),
|
color: AppColors.noir,
|
||||||
),
|
fontWeight: FontWeight.bold,
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
TextField(
|
|
||||||
controller: firstNameController,
|
|
||||||
decoration:
|
|
||||||
buildInputDecoration('Prénom', Icons.person_outline),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
TextField(
|
|
||||||
controller: lastNameController,
|
|
||||||
decoration: buildInputDecoration('Nom', Icons.person),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
TextField(
|
|
||||||
controller: emailController,
|
|
||||||
decoration:
|
|
||||||
buildInputDecoration('Email', Icons.email_outlined),
|
|
||||||
keyboardType: TextInputType.emailAddress,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
TextField(
|
|
||||||
controller: phoneController,
|
|
||||||
decoration: buildInputDecoration(
|
|
||||||
'Téléphone', Icons.phone_outlined),
|
|
||||||
keyboardType: TextInputType.phone,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
DropdownButtonFormField<String>(
|
|
||||||
value: selectedRole,
|
|
||||||
decoration: buildInputDecoration(
|
|
||||||
'Rôle', Icons.admin_panel_settings_outlined),
|
|
||||||
items: Roles.values.map((Role role) {
|
|
||||||
return DropdownMenuItem<String>(
|
|
||||||
value: role.name,
|
|
||||||
child: Text(role.name),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
onChanged: (String? newValue) {
|
|
||||||
if (newValue != null) {
|
|
||||||
selectedRole = newValue;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.pop(context),
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 16, vertical: 12),
|
|
||||||
),
|
|
||||||
child: const Text(
|
|
||||||
'Annuler',
|
|
||||||
style: TextStyle(color: AppColors.gris),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () async {
|
|
||||||
if (emailController.text.isEmpty ||
|
|
||||||
firstNameController.text.isEmpty ||
|
|
||||||
lastNameController.text.isEmpty) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'Veuillez remplir tous les champs obligatoires'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
final newUser = UserModel(
|
|
||||||
uid: '', // Sera généré par Firebase
|
|
||||||
firstName: firstNameController.text,
|
|
||||||
lastName: lastNameController.text,
|
|
||||||
email: emailController.text,
|
|
||||||
phoneNumber: phoneController.text,
|
|
||||||
role: selectedRole,
|
|
||||||
profilePhotoUrl: '',
|
|
||||||
);
|
|
||||||
|
|
||||||
final scaffoldMessenger = ScaffoldMessenger.of(context);
|
|
||||||
await Provider.of<UsersProvider>(context, listen: false)
|
|
||||||
.createUserWithEmailInvite(newUser);
|
|
||||||
|
|
||||||
if (context.mounted) {
|
|
||||||
Navigator.pop(context);
|
|
||||||
scaffoldMessenger.showSnackBar(
|
|
||||||
const SnackBar(
|
|
||||||
content: Text('Invitation envoyée avec succès'),
|
|
||||||
backgroundColor: Colors.green,
|
|
||||||
),
|
),
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (context.mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'Erreur lors de la création: ${e.toString()}'),
|
|
||||||
backgroundColor: Colors.red,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: AppColors.rouge,
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 24, vertical: 12),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: firstNameController,
|
||||||
|
decoration: buildInputDecoration(
|
||||||
|
'Prénom', Icons.person_outline),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextField(
|
||||||
|
controller: lastNameController,
|
||||||
|
decoration: buildInputDecoration('Nom', Icons.person),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextField(
|
||||||
|
controller: emailController,
|
||||||
|
decoration: buildInputDecoration(
|
||||||
|
'Email', Icons.email_outlined),
|
||||||
|
keyboardType: TextInputType.emailAddress,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
TextField(
|
||||||
|
controller: phoneController,
|
||||||
|
decoration: buildInputDecoration(
|
||||||
|
'Téléphone', Icons.phone_outlined),
|
||||||
|
keyboardType: TextInputType.phone,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
isLoadingRoles
|
||||||
|
? const CircularProgressIndicator()
|
||||||
|
: DropdownButtonFormField<String>(
|
||||||
|
value: selectedRoleId,
|
||||||
|
decoration: buildInputDecoration('Rôle',
|
||||||
|
Icons.admin_panel_settings_outlined),
|
||||||
|
items: availableRoles.map((role) {
|
||||||
|
return DropdownMenuItem<String>(
|
||||||
|
value: role.id,
|
||||||
|
child: Text(role.name),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (String? newValue) {
|
||||||
|
if (newValue != null) {
|
||||||
|
selectedRoleId = newValue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
child: const Text(
|
),
|
||||||
'Inviter',
|
const SizedBox(height: 24),
|
||||||
style: TextStyle(color: AppColors.blanc),
|
Row(
|
||||||
),
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16, vertical: 12),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'Annuler',
|
||||||
|
style: TextStyle(color: AppColors.gris),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
if (emailController.text.isEmpty ||
|
||||||
|
firstNameController.text.isEmpty ||
|
||||||
|
lastNameController.text.isEmpty ||
|
||||||
|
selectedRoleId == null) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
const SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Veuillez remplir tous les champs obligatoires'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final newUser = UserModel(
|
||||||
|
uid: '', // Sera généré par Firebase
|
||||||
|
firstName: firstNameController.text,
|
||||||
|
lastName: lastNameController.text,
|
||||||
|
email: emailController.text,
|
||||||
|
phoneNumber: phoneController.text,
|
||||||
|
role: selectedRoleId!,
|
||||||
|
profilePhotoUrl: '',
|
||||||
|
);
|
||||||
|
await Provider.of<UsersProvider>(context,
|
||||||
|
listen: false)
|
||||||
|
.createUserWithEmailInvite(context, newUser,
|
||||||
|
roleId: selectedRoleId);
|
||||||
|
Navigator.pop(context);
|
||||||
|
} catch (e) {
|
||||||
|
if (context.mounted) {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Erreur lors de la création: ${e.toString()}'),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: AppColors.rouge,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 24, vertical: 12),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: const Text(
|
||||||
|
'Inviter',
|
||||||
|
style: TextStyle(color: AppColors.blanc),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
878
em2rp/lib/views/widgets/calendar_widgets/event_details.dart
Normal file
878
em2rp/lib/views/widgets/calendar_widgets/event_details.dart
Normal file
@ -0,0 +1,878 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:em2rp/models/event_model.dart';
|
||||||
|
import 'package:em2rp/utils/colors.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:em2rp/providers/local_user_provider.dart';
|
||||||
|
import 'package:em2rp/providers/event_provider.dart';
|
||||||
|
import 'package:latlong2/latlong.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:em2rp/views/widgets/user_management/user_card.dart';
|
||||||
|
import 'package:em2rp/models/user_model.dart';
|
||||||
|
import 'package:em2rp/views/widgets/user_management/user_multi_select_widget.dart';
|
||||||
|
import 'package:em2rp/views/event_add_page.dart';
|
||||||
|
|
||||||
|
class EventDetails extends StatelessWidget {
|
||||||
|
final EventModel event;
|
||||||
|
final DateTime? selectedDate;
|
||||||
|
final List<EventModel> events;
|
||||||
|
final void Function(EventModel, DateTime) onSelectEvent;
|
||||||
|
|
||||||
|
const EventDetails({
|
||||||
|
super.key,
|
||||||
|
required this.event,
|
||||||
|
required this.selectedDate,
|
||||||
|
required this.events,
|
||||||
|
required this.onSelectEvent,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final dateFormat = DateFormat('dd/MM/yyyy HH:mm');
|
||||||
|
final currencyFormat = NumberFormat.currency(locale: 'fr_FR', symbol: '€');
|
||||||
|
final fullDateFormat = DateFormat('EEEE d MMMM y', 'fr_FR');
|
||||||
|
// Trie les événements par date de début
|
||||||
|
final sortedEvents = List<EventModel>.from(events)
|
||||||
|
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
||||||
|
final currentIndex = sortedEvents.indexWhere((e) => e.id == event.id);
|
||||||
|
final localUserProvider = Provider.of<LocalUserProvider>(context);
|
||||||
|
final isAdmin = localUserProvider.hasPermission('view_all_users');
|
||||||
|
final canViewPrices = localUserProvider.hasPermission('view_event_prices');
|
||||||
|
|
||||||
|
return Card(
|
||||||
|
margin: const EdgeInsets.all(16),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: currentIndex > 0
|
||||||
|
? () {
|
||||||
|
final prevEvent = sortedEvents[currentIndex - 1];
|
||||||
|
onSelectEvent(prevEvent, prevEvent.startDateTime);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
color: AppColors.rouge,
|
||||||
|
),
|
||||||
|
if (selectedDate != null)
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
fullDateFormat.format(selectedDate!),
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: AppColors.rouge,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: currentIndex < sortedEvents.length - 1
|
||||||
|
? () {
|
||||||
|
final nextEvent = sortedEvents[currentIndex + 1];
|
||||||
|
onSelectEvent(nextEvent, nextEvent.startDateTime);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
icon: const Icon(Icons.arrow_forward),
|
||||||
|
color: AppColors.rouge,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
SelectableText(
|
||||||
|
event.name,
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 12),
|
||||||
|
_buildStatusIcon(event.status),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Spacer(),
|
||||||
|
if (Provider.of<LocalUserProvider>(context, listen: false)
|
||||||
|
.hasPermission('edit_event'))
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.edit, color: AppColors.rouge),
|
||||||
|
tooltip: 'Modifier',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => EventAddEditPage(event: event),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (Provider.of<LocalUserProvider>(context, listen: false)
|
||||||
|
.hasPermission('change_event_status'))
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 12.0),
|
||||||
|
child: _FirestoreStatusButton(
|
||||||
|
eventId: event.id,
|
||||||
|
currentStatus: event.status,
|
||||||
|
onStatusChanged: (newStatus) async {
|
||||||
|
await FirebaseFirestore.instance
|
||||||
|
.collection('events')
|
||||||
|
.doc(event.id)
|
||||||
|
.update({'status': eventStatusToString(newStatus)});
|
||||||
|
// Recharge l'événement depuis Firestore et notifie le parent
|
||||||
|
final snap = await FirebaseFirestore.instance
|
||||||
|
.collection('events')
|
||||||
|
.doc(event.id)
|
||||||
|
.get();
|
||||||
|
final updatedEvent =
|
||||||
|
EventModel.fromMap(snap.data()!, event.id);
|
||||||
|
onSelectEvent(updatedEvent,
|
||||||
|
selectedDate ?? updatedEvent.startDateTime);
|
||||||
|
// Met à jour uniquement l'événement dans le provider (rafraîchissement local et fluide)
|
||||||
|
await Provider.of<EventProvider>(context, listen: false)
|
||||||
|
.updateEvent(updatedEvent);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildInfoRow(
|
||||||
|
context,
|
||||||
|
Icons.calendar_today,
|
||||||
|
'Date de début',
|
||||||
|
dateFormat.format(event.startDateTime),
|
||||||
|
),
|
||||||
|
_buildInfoRow(
|
||||||
|
context,
|
||||||
|
Icons.calendar_today,
|
||||||
|
'Date de fin',
|
||||||
|
dateFormat.format(event.endDateTime),
|
||||||
|
),
|
||||||
|
if (canViewPrices)
|
||||||
|
_buildInfoRow(
|
||||||
|
context,
|
||||||
|
Icons.euro,
|
||||||
|
'Prix de base',
|
||||||
|
currencyFormat.format(event.basePrice),
|
||||||
|
),
|
||||||
|
if (event.options.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text('Options sélectionnées',
|
||||||
|
style:
|
||||||
|
Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
)),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: event.options.map((opt) {
|
||||||
|
final price = (opt['price'] ?? 0.0) as num;
|
||||||
|
final isNegative = price < 0;
|
||||||
|
return ListTile(
|
||||||
|
leading: Icon(Icons.tune,
|
||||||
|
color:
|
||||||
|
isNegative ? Colors.red : AppColors.rouge),
|
||||||
|
title: Text(opt['name'] ?? '',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
subtitle: Text(opt['details'] ?? ''),
|
||||||
|
trailing: canViewPrices
|
||||||
|
? Text(
|
||||||
|
(isNegative ? '- ' : '+ ') +
|
||||||
|
currencyFormat.format(price.abs()),
|
||||||
|
style: TextStyle(
|
||||||
|
color: isNegative
|
||||||
|
? Colors.red
|
||||||
|
: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
dense: true,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
if (canViewPrices) ...[
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final total = event.basePrice +
|
||||||
|
event.options.fold<num>(0,
|
||||||
|
(sum, opt) => sum + (opt['price'] ?? 0.0));
|
||||||
|
return Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.only(top: 8.0, bottom: 8.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.attach_money,
|
||||||
|
color: AppColors.rouge),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text('Prix total : ',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleMedium
|
||||||
|
?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
)),
|
||||||
|
Text(
|
||||||
|
currencyFormat.format(total),
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleMedium
|
||||||
|
?.copyWith(
|
||||||
|
color: AppColors.rouge,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
_buildInfoRow(
|
||||||
|
context,
|
||||||
|
Icons.build,
|
||||||
|
'Temps d\'installation',
|
||||||
|
'${event.installationTime} heures',
|
||||||
|
),
|
||||||
|
_buildInfoRow(
|
||||||
|
context,
|
||||||
|
Icons.construction,
|
||||||
|
'Temps de démontage',
|
||||||
|
'${event.disassemblyTime} heures',
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Description',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
SelectableText(
|
||||||
|
event.description,
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Adresse',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
SelectableText(
|
||||||
|
event.address,
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
if (event.latitude != 0.0 || event.longitude != 0.0) ...[
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
SelectableText(
|
||||||
|
'${event.latitude}° N, ${event.longitude}° E',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
if (event.documents.isNotEmpty) ...[
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text('Documents',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleLarge
|
||||||
|
?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: event.documents.map((doc) {
|
||||||
|
final fileName = doc['name'] ?? '';
|
||||||
|
final url = doc['url'] ?? '';
|
||||||
|
final ext = p.extension(fileName).toLowerCase();
|
||||||
|
IconData icon;
|
||||||
|
if ([".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"]
|
||||||
|
.contains(ext)) {
|
||||||
|
icon = Icons.image;
|
||||||
|
} else if (ext == ".pdf") {
|
||||||
|
icon = Icons.picture_as_pdf;
|
||||||
|
} else if ([
|
||||||
|
".txt",
|
||||||
|
".md",
|
||||||
|
".csv",
|
||||||
|
".json",
|
||||||
|
".xml",
|
||||||
|
".docx",
|
||||||
|
".doc",
|
||||||
|
".xls",
|
||||||
|
".xlsx",
|
||||||
|
".ppt",
|
||||||
|
".pptx"
|
||||||
|
].contains(ext)) {
|
||||||
|
icon = Icons.description;
|
||||||
|
} else {
|
||||||
|
icon = Icons.attach_file;
|
||||||
|
}
|
||||||
|
return ListTile(
|
||||||
|
leading: Icon(icon, color: Colors.blueGrey),
|
||||||
|
title: SelectableText(
|
||||||
|
fileName,
|
||||||
|
maxLines: 1,
|
||||||
|
textAlign: TextAlign.left,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.download),
|
||||||
|
onPressed: () async {
|
||||||
|
if (await canLaunchUrl(Uri.parse(url))) {
|
||||||
|
await launchUrl(Uri.parse(url),
|
||||||
|
mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onTap: () async {
|
||||||
|
if (await canLaunchUrl(Uri.parse(url))) {
|
||||||
|
await launchUrl(Uri.parse(url),
|
||||||
|
mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
dense: true,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
// --- EQUIPE SECTION ---
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
EquipeSection(workforce: event.workforce),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInfoRow(
|
||||||
|
BuildContext context,
|
||||||
|
IconData icon,
|
||||||
|
String label,
|
||||||
|
String value,
|
||||||
|
) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Icon(icon, color: AppColors.rouge),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Text(
|
||||||
|
'$label : ',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
color: AppColors.noir,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildStatusIcon(EventStatus status) {
|
||||||
|
Color color;
|
||||||
|
IconData icon;
|
||||||
|
String tooltip;
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
color = Colors.green;
|
||||||
|
icon = Icons.check_circle;
|
||||||
|
tooltip = 'Confirmé';
|
||||||
|
break;
|
||||||
|
case EventStatus.canceled:
|
||||||
|
color = Colors.red;
|
||||||
|
icon = Icons.cancel;
|
||||||
|
tooltip = 'Annulé';
|
||||||
|
break;
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
color = Colors.amber;
|
||||||
|
icon = Icons.hourglass_empty;
|
||||||
|
tooltip = 'En attente de validation';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Tooltip(
|
||||||
|
message: tooltip,
|
||||||
|
child: Icon(icon, color: color, size: 28),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventAddDialog extends StatefulWidget {
|
||||||
|
const EventAddDialog({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<EventAddDialog> createState() => _EventAddDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EventAddDialogState extends State<EventAddDialog> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final TextEditingController _nameController = TextEditingController();
|
||||||
|
final TextEditingController _descriptionController = TextEditingController();
|
||||||
|
final TextEditingController _priceController = TextEditingController();
|
||||||
|
final TextEditingController _installationController = TextEditingController();
|
||||||
|
final TextEditingController _disassemblyController = TextEditingController();
|
||||||
|
final TextEditingController _latitudeController = TextEditingController();
|
||||||
|
final TextEditingController _longitudeController = TextEditingController();
|
||||||
|
final TextEditingController _addressController = TextEditingController();
|
||||||
|
DateTime? _startDateTime;
|
||||||
|
DateTime? _endDateTime;
|
||||||
|
bool _isLoading = false;
|
||||||
|
String? _error;
|
||||||
|
String? _success;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_nameController.dispose();
|
||||||
|
_descriptionController.dispose();
|
||||||
|
_priceController.dispose();
|
||||||
|
_installationController.dispose();
|
||||||
|
_disassemblyController.dispose();
|
||||||
|
_latitudeController.dispose();
|
||||||
|
_longitudeController.dispose();
|
||||||
|
_addressController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _submit() async {
|
||||||
|
if (!_formKey.currentState!.validate() ||
|
||||||
|
_startDateTime == null ||
|
||||||
|
_endDateTime == null) return;
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
_error = null;
|
||||||
|
_success = null;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final eventProvider = Provider.of<EventProvider>(context, listen: false);
|
||||||
|
final newEvent = EventModel(
|
||||||
|
id: '',
|
||||||
|
name: _nameController.text.trim(),
|
||||||
|
description: _descriptionController.text.trim(),
|
||||||
|
startDateTime: _startDateTime!,
|
||||||
|
endDateTime: _endDateTime!,
|
||||||
|
basePrice: double.tryParse(_priceController.text) ?? 0.0,
|
||||||
|
installationTime: int.tryParse(_installationController.text) ?? 0,
|
||||||
|
disassemblyTime: int.tryParse(_disassemblyController.text) ?? 0,
|
||||||
|
eventTypeId: '', // à adapter si tu veux gérer les types
|
||||||
|
customerId: '', // à adapter si tu veux gérer les clients
|
||||||
|
address: _addressController.text.trim(),
|
||||||
|
latitude: double.tryParse(_latitudeController.text) ?? 0.0,
|
||||||
|
longitude: double.tryParse(_longitudeController.text) ?? 0.0,
|
||||||
|
workforce: [],
|
||||||
|
documents: [],
|
||||||
|
);
|
||||||
|
await eventProvider.addEvent(newEvent);
|
||||||
|
setState(() {
|
||||||
|
_success = "Événement créé avec succès !";
|
||||||
|
});
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_error = "Erreur lors de la création : $e";
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Créer un événement'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Nom'),
|
||||||
|
validator: (v) =>
|
||||||
|
v == null || v.isEmpty ? 'Champ requis' : null,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _descriptionController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Description'),
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _priceController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Prix (€)'),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _installationController,
|
||||||
|
decoration:
|
||||||
|
const InputDecoration(labelText: 'Installation (h)'),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _disassemblyController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Démontage (h)'),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _latitudeController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Latitude'),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _longitudeController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Longitude'),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
),
|
||||||
|
TextFormField(
|
||||||
|
controller: _addressController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Adresse'),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: DateTime.now(),
|
||||||
|
firstDate: DateTime(2020),
|
||||||
|
lastDate: DateTime(2030),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final time = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (time != null) {
|
||||||
|
setState(() {
|
||||||
|
_startDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
time.hour,
|
||||||
|
time.minute,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(_startDateTime == null
|
||||||
|
? 'Début'
|
||||||
|
: DateFormat('dd/MM/yyyy HH:mm')
|
||||||
|
.format(_startDateTime!)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
final picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: _startDateTime ?? DateTime.now(),
|
||||||
|
firstDate: DateTime(2020),
|
||||||
|
lastDate: DateTime(2030),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
final time = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.now(),
|
||||||
|
);
|
||||||
|
if (time != null) {
|
||||||
|
setState(() {
|
||||||
|
_endDateTime = DateTime(
|
||||||
|
picked.year,
|
||||||
|
picked.month,
|
||||||
|
picked.day,
|
||||||
|
time.hour,
|
||||||
|
time.minute,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(_endDateTime == null
|
||||||
|
? 'Fin'
|
||||||
|
: DateFormat('dd/MM/yyyy HH:mm')
|
||||||
|
.format(_endDateTime!)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (_error != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child:
|
||||||
|
Text(_error!, style: const TextStyle(color: Colors.red)),
|
||||||
|
),
|
||||||
|
if (_success != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child: Text(_success!,
|
||||||
|
style: const TextStyle(color: Colors.green)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: _isLoading ? null : () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _isLoading ? null : _submit,
|
||||||
|
child: _isLoading
|
||||||
|
? const SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
)
|
||||||
|
: const Text('Créer'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FirestoreStatusButton extends StatefulWidget {
|
||||||
|
final String eventId;
|
||||||
|
final EventStatus currentStatus;
|
||||||
|
final Future<void> Function(EventStatus) onStatusChanged;
|
||||||
|
const _FirestoreStatusButton({
|
||||||
|
required this.eventId,
|
||||||
|
required this.currentStatus,
|
||||||
|
required this.onStatusChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_FirestoreStatusButton> createState() => _FirestoreStatusButtonState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _FirestoreStatusButtonState extends State<_FirestoreStatusButton> {
|
||||||
|
bool _loading = false;
|
||||||
|
|
||||||
|
Future<void> changerStatut(EventStatus nouveau) async {
|
||||||
|
if (widget.currentStatus == nouveau) return;
|
||||||
|
setState(() => _loading = true);
|
||||||
|
await widget.onStatusChanged(nouveau);
|
||||||
|
setState(() => _loading = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant _FirestoreStatusButton oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
// Si l'événement change, on arrête le loading (sécurité UX)
|
||||||
|
if (oldWidget.eventId != widget.eventId ||
|
||||||
|
oldWidget.currentStatus != widget.currentStatus) {
|
||||||
|
if (_loading) setState(() => _loading = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final status = widget.currentStatus;
|
||||||
|
String texte;
|
||||||
|
Color couleurFond;
|
||||||
|
List<Widget> enfants = [];
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
texte = "En Attente";
|
||||||
|
couleurFond = Colors.yellow.shade600;
|
||||||
|
enfants = [
|
||||||
|
_buildIconButton(Icons.close, Colors.red,
|
||||||
|
() => changerStatut(EventStatus.canceled)),
|
||||||
|
_buildLabel(texte, couleurFond),
|
||||||
|
_buildIconButton(Icons.check, Colors.green,
|
||||||
|
() => changerStatut(EventStatus.confirmed)),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
texte = "Confirmé";
|
||||||
|
couleurFond = Colors.green;
|
||||||
|
enfants = [
|
||||||
|
_buildIconButton(Icons.close, Colors.red,
|
||||||
|
() => changerStatut(EventStatus.canceled)),
|
||||||
|
_buildIconButton(Icons.hourglass_empty, Colors.yellow.shade700,
|
||||||
|
() => changerStatut(EventStatus.waitingForApproval)),
|
||||||
|
_buildLabel(texte, couleurFond),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
case EventStatus.canceled:
|
||||||
|
texte = "Annulé";
|
||||||
|
couleurFond = Colors.red;
|
||||||
|
enfants = [
|
||||||
|
_buildLabel(texte, couleurFond),
|
||||||
|
_buildIconButton(Icons.hourglass_empty, Colors.yellow.shade700,
|
||||||
|
() => changerStatut(EventStatus.waitingForApproval)),
|
||||||
|
_buildIconButton(Icons.check, Colors.green,
|
||||||
|
() => changerStatut(EventStatus.confirmed)),
|
||||||
|
];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
padding: const EdgeInsets.all(2),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Colors.transparent,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: enfants,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildLabel(String texte, Color couleur) {
|
||||||
|
return AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 2),
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: couleur,
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
child: Text(
|
||||||
|
texte,
|
||||||
|
key: ValueKey(texte),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold, color: Colors.white, fontSize: 13),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildIconButton(
|
||||||
|
IconData icone, Color couleur, VoidCallback onPressed) {
|
||||||
|
return AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 2),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: couleur, width: 1.5),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: IconButton(
|
||||||
|
icon: Icon(icone, color: couleur, size: 16),
|
||||||
|
onPressed: _loading ? null : onPressed,
|
||||||
|
splashRadius: 16,
|
||||||
|
tooltip: 'Changer statut',
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
constraints: const BoxConstraints(minWidth: 28, minHeight: 28),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EquipeSection extends StatelessWidget {
|
||||||
|
final List workforce;
|
||||||
|
const EquipeSection({super.key, required this.workforce});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (workforce.isEmpty) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Equipe',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text('Aucun membre assigné.',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return FutureBuilder<List<UserModel>>(
|
||||||
|
future: _fetchUsers(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
|
return const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
child: Center(child: CircularProgressIndicator()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (snapshot.hasError) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
child: Text(
|
||||||
|
snapshot.error.toString().contains('permission-denied')
|
||||||
|
? "Vous n'avez pas la permission de voir tous les membres de l'équipe."
|
||||||
|
: "Erreur lors du chargement de l'équipe : ${snapshot.error}",
|
||||||
|
style: const TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final users = snapshot.data ?? [];
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Equipe',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
)),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
if (users.isEmpty)
|
||||||
|
Text('Aucun membre assigné.',
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium),
|
||||||
|
if (users.isNotEmpty)
|
||||||
|
UserChipsList(
|
||||||
|
users: users,
|
||||||
|
showRemove: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<UserModel>> _fetchUsers() async {
|
||||||
|
final firestore = FirebaseFirestore.instance;
|
||||||
|
List<UserModel> users = [];
|
||||||
|
for (final ref in workforce) {
|
||||||
|
try {
|
||||||
|
final doc = await firestore.doc(ref.path).get();
|
||||||
|
if (doc.exists) {
|
||||||
|
users.add(
|
||||||
|
UserModel.fromMap(doc.data() as Map<String, dynamic>, doc.id));
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,139 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:em2rp/models/event_model.dart';
|
||||||
|
|
||||||
|
class MobileCalendarView extends StatelessWidget {
|
||||||
|
final DateTime focusedDay;
|
||||||
|
final DateTime? selectedDay;
|
||||||
|
final List<EventModel> events;
|
||||||
|
final void Function(DateTime) onDaySelected;
|
||||||
|
|
||||||
|
const MobileCalendarView({
|
||||||
|
super.key,
|
||||||
|
required this.focusedDay,
|
||||||
|
required this.selectedDay,
|
||||||
|
required this.events,
|
||||||
|
required this.onDaySelected,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final daysInMonth =
|
||||||
|
DateUtils.getDaysInMonth(focusedDay.year, focusedDay.month);
|
||||||
|
final firstDayOfMonth = DateTime(focusedDay.year, focusedDay.month, 1);
|
||||||
|
final firstWeekday = firstDayOfMonth.weekday;
|
||||||
|
final days = <DateTime>[];
|
||||||
|
// Ajoute les jours vides avant le 1er du mois (pour aligner sur le bon jour de la semaine)
|
||||||
|
for (int i = 1; i < firstWeekday; i++) {
|
||||||
|
days.add(DateTime(0)); // jour vide
|
||||||
|
}
|
||||||
|
// Ajoute les jours du mois
|
||||||
|
for (int i = 0; i < daysInMonth; i++) {
|
||||||
|
days.add(DateTime(focusedDay.year, focusedDay.month, i + 1));
|
||||||
|
}
|
||||||
|
// Complète la dernière semaine si besoin
|
||||||
|
while (days.length % 7 != 0) {
|
||||||
|
days.add(DateTime(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: List.generate(7, (i) {
|
||||||
|
const daysShort = ['L', 'M', 'M', 'J', 'V', 'S', 'D'];
|
||||||
|
return Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(daysShort[i],
|
||||||
|
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...List.generate(days.length ~/ 7, (week) {
|
||||||
|
return Row(
|
||||||
|
children: List.generate(7, (i) {
|
||||||
|
final day = days[week * 7 + i];
|
||||||
|
if (day.year == 0) {
|
||||||
|
return const Expanded(child: SizedBox.shrink());
|
||||||
|
}
|
||||||
|
final isSelected =
|
||||||
|
selectedDay != null && _isSameDay(day, selectedDay!);
|
||||||
|
final eventsForDay = events
|
||||||
|
.where((e) => _isSameDay(e.startDateTime, day))
|
||||||
|
.toList();
|
||||||
|
return Expanded(
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () => onDaySelected(day),
|
||||||
|
child: Container(
|
||||||
|
color: Colors.transparent,
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: isSelected
|
||||||
|
? BoxDecoration(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.primary
|
||||||
|
.withOpacity(0.15),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Text(
|
||||||
|
'${day.day}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: isSelected
|
||||||
|
? Theme.of(context).colorScheme.primary
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 2),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: eventsForDay
|
||||||
|
.map((event) => Container(
|
||||||
|
margin: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 1),
|
||||||
|
width: 6,
|
||||||
|
height: 6,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: _getColorForStatus(event.status),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _isSameDay(DateTime a, DateTime b) {
|
||||||
|
return a.year == b.year && a.month == b.month && a.day == b.day;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _getColorForStatus(EventStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
return Colors.green;
|
||||||
|
case EventStatus.canceled:
|
||||||
|
return Colors.red;
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
return Colors.amber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -213,6 +213,27 @@ class MonthView extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _buildEventItem(
|
Widget _buildEventItem(
|
||||||
EventModel event, bool isSelected, DateTime currentDay) {
|
EventModel event, bool isSelected, DateTime currentDay) {
|
||||||
|
Color color;
|
||||||
|
Color textColor;
|
||||||
|
IconData icon;
|
||||||
|
switch (event.status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
color = Colors.green;
|
||||||
|
textColor = Colors.white;
|
||||||
|
icon = Icons.check;
|
||||||
|
break;
|
||||||
|
case EventStatus.canceled:
|
||||||
|
color = Colors.red;
|
||||||
|
textColor = Colors.white;
|
||||||
|
icon = Icons.close;
|
||||||
|
break;
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
color = Colors.amber;
|
||||||
|
textColor = Colors.black;
|
||||||
|
icon = Icons.hourglass_empty;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
onDaySelected(currentDay, currentDay);
|
onDaySelected(currentDay, currentDay);
|
||||||
@ -222,33 +243,40 @@ class MonthView extends StatelessWidget {
|
|||||||
margin: const EdgeInsets.only(bottom: 2),
|
margin: const EdgeInsets.only(bottom: 2),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isSelected
|
color: isSelected ? color.withAlpha(220) : color.withOpacity(0.18),
|
||||||
? Colors.white.withAlpha(51)
|
|
||||||
: AppColors.rouge.withAlpha(26),
|
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Icon(icon, color: textColor, size: 16),
|
||||||
event.name,
|
const SizedBox(width: 4),
|
||||||
style: TextStyle(
|
Expanded(
|
||||||
fontSize: 12,
|
child: Column(
|
||||||
color: isSelected ? Colors.white : AppColors.rouge,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
fontWeight: FontWeight.bold,
|
children: [
|
||||||
|
Text(
|
||||||
|
event.name,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: textColor,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
if (CalendarUtils.isMultiDayEvent(event))
|
||||||
|
Text(
|
||||||
|
'Jour ${CalendarUtils.calculateDayNumber(event.startDateTime, currentDay)}/${CalendarUtils.calculateTotalDays(event)}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 10,
|
||||||
|
color: textColor,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
),
|
||||||
if (CalendarUtils.isMultiDayEvent(event))
|
|
||||||
Text(
|
|
||||||
'Jour ${CalendarUtils.calculateDayNumber(event.startDateTime, event.startDateTime)}/${CalendarUtils.calculateTotalDays(event)}',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 10,
|
|
||||||
color: isSelected ? Colors.white : AppColors.rouge,
|
|
||||||
),
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -9,6 +9,8 @@ class WeekView extends StatelessWidget {
|
|||||||
final Function(int) onWeekChange;
|
final Function(int) onWeekChange;
|
||||||
final Function(EventModel) onEventSelected;
|
final Function(EventModel) onEventSelected;
|
||||||
final Function() onSwitchToMonth;
|
final Function() onSwitchToMonth;
|
||||||
|
final Function(DateTime) onDaySelected;
|
||||||
|
final EventModel? selectedEvent;
|
||||||
|
|
||||||
const WeekView({
|
const WeekView({
|
||||||
super.key,
|
super.key,
|
||||||
@ -17,6 +19,8 @@ class WeekView extends StatelessWidget {
|
|||||||
required this.onWeekChange,
|
required this.onWeekChange,
|
||||||
required this.onEventSelected,
|
required this.onEventSelected,
|
||||||
required this.onSwitchToMonth,
|
required this.onSwitchToMonth,
|
||||||
|
required this.onDaySelected,
|
||||||
|
required this.selectedEvent,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -253,6 +257,8 @@ class WeekView extends StatelessWidget {
|
|||||||
final endHour = e.end.hour + e.end.minute / 60;
|
final endHour = e.end.hour + e.end.minute / 60;
|
||||||
final duration = endHour - startHour;
|
final duration = endHour - startHour;
|
||||||
final width = dayWidth / e.totalColumns;
|
final width = dayWidth / e.totalColumns;
|
||||||
|
final isSelected =
|
||||||
|
selectedEvent != null && e.event.id == selectedEvent!.id;
|
||||||
|
|
||||||
return Positioned(
|
return Positioned(
|
||||||
left: dayIdx * dayWidth + e.column * width,
|
left: dayIdx * dayWidth + e.column * width,
|
||||||
@ -265,32 +271,44 @@ class WeekView extends StatelessWidget {
|
|||||||
margin: const EdgeInsets.all(2),
|
margin: const EdgeInsets.all(2),
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: AppColors.rouge.withAlpha(26),
|
color: isSelected
|
||||||
border: Border.all(color: AppColors.rouge),
|
? _getStatusColor(e.event.status).withAlpha(220)
|
||||||
|
: _getStatusColor(e.event.status).withOpacity(0.18),
|
||||||
|
border: Border.all(
|
||||||
|
color: _getStatusColor(e.event.status),
|
||||||
|
width: isSelected ? 3 : 1,
|
||||||
|
),
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Expanded(
|
||||||
e.event.name,
|
child: Column(
|
||||||
style: const TextStyle(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
color: AppColors.rouge,
|
children: [
|
||||||
fontSize: 12,
|
Text(
|
||||||
fontWeight: FontWeight.bold,
|
e.event.name,
|
||||||
|
style: TextStyle(
|
||||||
|
color: _getStatusTextColor(e.event.status),
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
if (CalendarUtils.isMultiDayEvent(e.event))
|
||||||
|
Text(
|
||||||
|
'Jour ${CalendarUtils.calculateDayNumber(e.event.startDateTime, weekStart.add(Duration(days: dayIdx)))}/${CalendarUtils.calculateTotalDays(e.event)}',
|
||||||
|
style: TextStyle(
|
||||||
|
color: _getStatusTextColor(e.event.status),
|
||||||
|
fontSize: 10,
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
),
|
||||||
if (CalendarUtils.isMultiDayEvent(e.event))
|
|
||||||
Text(
|
|
||||||
'Jour ${CalendarUtils.calculateDayNumber(e.event.startDateTime, weekStart.add(Duration(days: dayIdx)))}/${CalendarUtils.calculateTotalDays(e.event)}',
|
|
||||||
style: const TextStyle(
|
|
||||||
color: AppColors.rouge,
|
|
||||||
fontSize: 10,
|
|
||||||
),
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -366,6 +384,41 @@ class WeekView extends StatelessWidget {
|
|||||||
bool _overlap(_PositionedEvent a, _PositionedEvent b) {
|
bool _overlap(_PositionedEvent a, _PositionedEvent b) {
|
||||||
return a.end.isAfter(b.start) && a.start.isBefore(b.end);
|
return a.end.isAfter(b.start) && a.start.isBefore(b.end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color _getStatusColor(EventStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
return Colors.green;
|
||||||
|
case EventStatus.canceled:
|
||||||
|
return Colors.red;
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
return Colors.amber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _getStatusTextColor(EventStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
case EventStatus.canceled:
|
||||||
|
return Colors.white;
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
return Colors.black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconData _getStatusIcon(EventStatus status) {
|
||||||
|
switch (status) {
|
||||||
|
case EventStatus.confirmed:
|
||||||
|
return Icons.check;
|
||||||
|
case EventStatus.canceled:
|
||||||
|
return Icons.close;
|
||||||
|
case EventStatus.waitingForApproval:
|
||||||
|
default:
|
||||||
|
return Icons.hourglass_empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PositionedEvent {
|
class _PositionedEvent {
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
|
||||||
class ProfilePictureWidget extends StatelessWidget {
|
class ProfilePictureWidget extends StatefulWidget {
|
||||||
final String? userId; // Modifié pour être nullable
|
final String? userId;
|
||||||
final double radius;
|
final double radius;
|
||||||
final String? defaultImageUrl;
|
final String? defaultImageUrl;
|
||||||
|
|
||||||
@ -13,28 +13,58 @@ class ProfilePictureWidget extends StatelessWidget {
|
|||||||
this.defaultImageUrl,
|
this.defaultImageUrl,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ProfilePictureWidget> createState() => _ProfilePictureWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ProfilePictureWidgetState extends State<ProfilePictureWidget> {
|
||||||
|
late Future<DocumentSnapshot?> _userFuture;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_userFuture = _getUserFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(ProfilePictureWidget oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.userId != widget.userId) {
|
||||||
|
_userFuture = _getUserFuture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DocumentSnapshot?> _getUserFuture() {
|
||||||
|
if (widget.userId == null || widget.userId!.isEmpty) {
|
||||||
|
return Future.value(null);
|
||||||
|
}
|
||||||
|
return FirebaseFirestore.instance
|
||||||
|
.collection('users')
|
||||||
|
.doc(widget.userId)
|
||||||
|
.get();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
// Vérifier si userId est null ou vide
|
if (widget.userId == null || widget.userId!.isEmpty) {
|
||||||
if (userId == null || userId!.isEmpty) {
|
return _buildDefaultAvatar(widget.radius, widget.defaultImageUrl);
|
||||||
return _buildDefaultAvatar(radius, defaultImageUrl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FutureBuilder<DocumentSnapshot>(
|
return FutureBuilder<DocumentSnapshot?>(
|
||||||
future: FirebaseFirestore.instance.collection('users').doc(userId).get(),
|
future: _userFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||||
return _buildLoadingAvatar(radius);
|
return _buildLoadingAvatar(widget.radius);
|
||||||
} else if (snapshot.hasError) {
|
} else if (snapshot.hasError) {
|
||||||
print("Error loading profile: ${snapshot.error}");
|
print("Error loading profile: ${snapshot.error}");
|
||||||
return _buildDefaultAvatar(radius, defaultImageUrl);
|
return _buildDefaultAvatar(widget.radius, widget.defaultImageUrl);
|
||||||
} else if (snapshot.data != null && snapshot.data!.exists) {
|
} else if (snapshot.data != null && snapshot.data!.exists) {
|
||||||
final userData = snapshot.data!.data() as Map<String, dynamic>?;
|
final userData = snapshot.data!.data() as Map<String, dynamic>?;
|
||||||
final profilePhotoUrl = userData?['profilePhotoUrl'] as String?;
|
final profilePhotoUrl = userData?['profilePhotoUrl'] as String?;
|
||||||
|
|
||||||
if (profilePhotoUrl != null && profilePhotoUrl.isNotEmpty) {
|
if (profilePhotoUrl != null && profilePhotoUrl.isNotEmpty) {
|
||||||
return CircleAvatar(
|
return CircleAvatar(
|
||||||
radius: radius,
|
radius: widget.radius,
|
||||||
backgroundImage: NetworkImage(profilePhotoUrl),
|
backgroundImage: NetworkImage(profilePhotoUrl),
|
||||||
onBackgroundImageError: (e, stack) {
|
onBackgroundImageError: (e, stack) {
|
||||||
print("Error loading profile image: $e");
|
print("Error loading profile image: $e");
|
||||||
@ -42,7 +72,7 @@ class ProfilePictureWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _buildDefaultAvatar(radius, defaultImageUrl);
|
return _buildDefaultAvatar(widget.radius, widget.defaultImageUrl);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -88,7 +118,10 @@ class ProfilePictureWidget extends StatelessWidget {
|
|||||||
Widget _buildIconAvatar(double radius) {
|
Widget _buildIconAvatar(double radius) {
|
||||||
return CircleAvatar(
|
return CircleAvatar(
|
||||||
radius: radius,
|
radius: radius,
|
||||||
child: Icon(Icons.account_circle, size: radius * 1.5), // Icône par défaut
|
child: FittedBox(
|
||||||
|
fit: BoxFit.scaleDown,
|
||||||
|
child: Icon(Icons.account_circle, size: radius * 1.5),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
260
em2rp/lib/views/widgets/inputs/dropzone_upload_widget.dart
Normal file
260
em2rp/lib/views/widgets/inputs/dropzone_upload_widget.dart
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:firebase_storage/firebase_storage.dart';
|
||||||
|
import 'package:flutter_dropzone/flutter_dropzone.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
class DropzoneUploadWidget extends StatefulWidget {
|
||||||
|
final List<Map<String, String>> uploadedFiles;
|
||||||
|
final ValueChanged<List<Map<String, String>>> onFilesChanged;
|
||||||
|
final bool isLoading;
|
||||||
|
final String? error;
|
||||||
|
final String? success;
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
|
||||||
|
const DropzoneUploadWidget({
|
||||||
|
super.key,
|
||||||
|
required this.uploadedFiles,
|
||||||
|
required this.onFilesChanged,
|
||||||
|
this.isLoading = false,
|
||||||
|
this.error,
|
||||||
|
this.success,
|
||||||
|
this.width = 400,
|
||||||
|
this.height = 200,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DropzoneUploadWidget> createState() => _DropzoneUploadWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DropzoneUploadWidgetState extends State<DropzoneUploadWidget> {
|
||||||
|
DropzoneViewController? _dropzoneController;
|
||||||
|
bool _isDropzoneHighlighted = false;
|
||||||
|
bool _isLoading = false;
|
||||||
|
String? _error;
|
||||||
|
String? _success;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_isLoading = widget.isLoading;
|
||||||
|
_error = widget.error;
|
||||||
|
_success = widget.success;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _handleFiles(List<dynamic> files) async {
|
||||||
|
setState(() => _isLoading = true);
|
||||||
|
try {
|
||||||
|
List<Map<String, String>> newFiles = List.from(widget.uploadedFiles);
|
||||||
|
for (final file in files) {
|
||||||
|
final name = await _dropzoneController!.getFilename(file);
|
||||||
|
final bytes = await _dropzoneController!.getFileData(file);
|
||||||
|
if (bytes != null) {
|
||||||
|
final ref = FirebaseStorage.instance.ref().child(
|
||||||
|
'events/temp/${DateTime.now().millisecondsSinceEpoch}_$name');
|
||||||
|
final uploadTask = await ref.putData(bytes);
|
||||||
|
final url = await uploadTask.ref.getDownloadURL();
|
||||||
|
if (!newFiles.any((f) => f['name'] == name && f['url'] == url)) {
|
||||||
|
newFiles.add({'name': name, 'url': url});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
widget.onFilesChanged(newFiles);
|
||||||
|
setState(() {
|
||||||
|
_success = "Fichier(s) ajouté(s) !";
|
||||||
|
_error = null;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_error = 'Erreur lors de l\'upload : $e';
|
||||||
|
_success = null;
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
_isDropzoneHighlighted = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizedBox(
|
||||||
|
width: widget.width,
|
||||||
|
height: widget.height,
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
color: _isDropzoneHighlighted ? Colors.blue : Colors.grey,
|
||||||
|
width: 2,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
color: _isDropzoneHighlighted ? Colors.blue.withOpacity(0.1) : null,
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
DropzoneView(
|
||||||
|
onCreated: (controller) => _dropzoneController = controller,
|
||||||
|
onDropFiles: (files) async {
|
||||||
|
if (files == null) return;
|
||||||
|
await _handleFiles(files);
|
||||||
|
},
|
||||||
|
onHover: () => setState(() => _isDropzoneHighlighted = true),
|
||||||
|
onLeave: () => setState(() => _isDropzoneHighlighted = false),
|
||||||
|
),
|
||||||
|
Positioned.fill(
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: widget.uploadedFiles.isEmpty
|
||||||
|
? Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const Icon(Icons.cloud_upload,
|
||||||
|
size: 48, color: Colors.grey),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
const Text(
|
||||||
|
'Glissez-déposez des fichiers ici ou cliquez sur "Ajouter"',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(color: Colors.grey, fontSize: 16),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (widget.uploadedFiles.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: _buildFileListAndButton(),
|
||||||
|
),
|
||||||
|
if (widget.uploadedFiles.isEmpty)
|
||||||
|
Positioned(
|
||||||
|
bottom: 16,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 160,
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.attach_file, size: 18),
|
||||||
|
label: const Text('Ajouter'),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8, vertical: 8),
|
||||||
|
minimumSize: const Size(80, 36),
|
||||||
|
textStyle: const TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
|
onPressed: _isLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
final files =
|
||||||
|
await _dropzoneController?.pickFiles();
|
||||||
|
if (files != null) {
|
||||||
|
await _handleFiles(files);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_isLoading)
|
||||||
|
const Positioned.fill(
|
||||||
|
child: ColoredBox(
|
||||||
|
color: Color.fromARGB(80, 255, 255, 255),
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_error != null)
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(top: 8.0),
|
||||||
|
child:
|
||||||
|
Text(_error!, style: const TextStyle(color: Colors.red)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (_success != null)
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 32.0),
|
||||||
|
child: Text(_success!,
|
||||||
|
style: const TextStyle(color: Colors.green)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildFileListAndButton() {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
...widget.uploadedFiles.map((file) {
|
||||||
|
final fileName = file['name']!;
|
||||||
|
final ext = p.extension(fileName).toLowerCase();
|
||||||
|
IconData icon;
|
||||||
|
if ([".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"]
|
||||||
|
.contains(ext)) {
|
||||||
|
icon = Icons.image;
|
||||||
|
} else if (ext == ".pdf") {
|
||||||
|
icon = Icons.picture_as_pdf;
|
||||||
|
} else if ([".txt", ".md", ".csv", ".json", ".xml"].contains(ext)) {
|
||||||
|
icon = Icons.description;
|
||||||
|
} else {
|
||||||
|
icon = Icons.attach_file;
|
||||||
|
}
|
||||||
|
return ListTile(
|
||||||
|
leading: Icon(icon, color: Colors.blueGrey),
|
||||||
|
title: Text(fileName, overflow: TextOverflow.ellipsis),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.close),
|
||||||
|
onPressed: _isLoading
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
final newFiles =
|
||||||
|
List<Map<String, String>>.from(widget.uploadedFiles)
|
||||||
|
..remove(file);
|
||||||
|
widget.onFilesChanged(newFiles);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
dense: true,
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
SizedBox(
|
||||||
|
width: 160,
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.attach_file, size: 18),
|
||||||
|
label: const Text('Ajouter'),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||||
|
minimumSize: const Size(80, 36),
|
||||||
|
textStyle: const TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
|
onPressed: _isLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
final files = await _dropzoneController?.pickFiles();
|
||||||
|
if (files != null) {
|
||||||
|
await _handleFiles(files);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
87
em2rp/lib/views/widgets/inputs/int_stepper_field.dart
Normal file
87
em2rp/lib/views/widgets/inputs/int_stepper_field.dart
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class IntStepperField extends StatelessWidget {
|
||||||
|
final String label;
|
||||||
|
final TextEditingController controller;
|
||||||
|
final int min;
|
||||||
|
final int max;
|
||||||
|
|
||||||
|
const IntStepperField({
|
||||||
|
super.key,
|
||||||
|
required this.label,
|
||||||
|
required this.controller,
|
||||||
|
this.min = 0,
|
||||||
|
this.max = 24,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
int value = int.tryParse(controller.text) ?? 0;
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 2.0),
|
||||||
|
child: Text(
|
||||||
|
label,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.black87,
|
||||||
|
fontWeight: FontWeight.w500),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.remove_circle_outline, size: 20),
|
||||||
|
splashRadius: 18,
|
||||||
|
onPressed: value > min
|
||||||
|
? () {
|
||||||
|
value--;
|
||||||
|
controller.text = value.toString();
|
||||||
|
(context as Element).markNeedsBuild();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 60,
|
||||||
|
height: 36,
|
||||||
|
child: TextFormField(
|
||||||
|
controller: controller,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 15),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
contentPadding:
|
||||||
|
EdgeInsets.symmetric(vertical: 6, horizontal: 6),
|
||||||
|
),
|
||||||
|
onChanged: (val) {
|
||||||
|
int? v = int.tryParse(val);
|
||||||
|
if (v == null || v < min) {
|
||||||
|
controller.text = min.toString();
|
||||||
|
} else if (v > max) {
|
||||||
|
controller.text = max.toString();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.add_circle_outline, size: 20),
|
||||||
|
splashRadius: 18,
|
||||||
|
onPressed: value < max
|
||||||
|
? () {
|
||||||
|
value++;
|
||||||
|
controller.text = value.toString();
|
||||||
|
(context as Element).markNeedsBuild();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
467
em2rp/lib/views/widgets/inputs/option_selector_widget.dart
Normal file
467
em2rp/lib/views/widgets/inputs/option_selector_widget.dart
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:em2rp/models/option_model.dart';
|
||||||
|
|
||||||
|
class OptionSelectorWidget extends StatefulWidget {
|
||||||
|
final String? eventType;
|
||||||
|
final List<Map<String, dynamic>> selectedOptions;
|
||||||
|
final ValueChanged<List<Map<String, dynamic>>> onChanged;
|
||||||
|
final void Function(String name)? onRemove;
|
||||||
|
final bool eventTypeRequired;
|
||||||
|
final bool isMobile;
|
||||||
|
|
||||||
|
const OptionSelectorWidget({
|
||||||
|
super.key,
|
||||||
|
required this.eventType,
|
||||||
|
required this.selectedOptions,
|
||||||
|
required this.onChanged,
|
||||||
|
this.onRemove,
|
||||||
|
this.eventTypeRequired = false,
|
||||||
|
this.isMobile = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<OptionSelectorWidget> createState() => _OptionSelectorWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OptionSelectorWidgetState extends State<OptionSelectorWidget> {
|
||||||
|
List<EventOption> _allOptions = [];
|
||||||
|
bool _loading = true;
|
||||||
|
String _search = '';
|
||||||
|
final List<String> _eventTypes = ['Bal', 'Mariage', 'Anniversaire'];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant OptionSelectorWidget oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.eventType != widget.eventType) {
|
||||||
|
_fetchOptions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_fetchOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchOptions() async {
|
||||||
|
setState(() => _loading = true);
|
||||||
|
final snapshot =
|
||||||
|
await FirebaseFirestore.instance.collection('options').get();
|
||||||
|
final options = snapshot.docs
|
||||||
|
.map((doc) => EventOption.fromMap(doc.data(), doc.id))
|
||||||
|
.toList();
|
||||||
|
setState(() {
|
||||||
|
_allOptions = options;
|
||||||
|
_loading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showOptionPicker() async {
|
||||||
|
final selected = await showDialog<Map<String, dynamic>>(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => _OptionPickerDialog(
|
||||||
|
allOptions: _allOptions,
|
||||||
|
eventType: widget.eventType,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (selected != null) {
|
||||||
|
final newList = List<Map<String, dynamic>>.from(widget.selectedOptions)
|
||||||
|
..add(selected);
|
||||||
|
widget.onChanged(newList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Text('Options sélectionnées',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Column(
|
||||||
|
children: widget.selectedOptions
|
||||||
|
.map((opt) => Card(
|
||||||
|
elevation: widget.isMobile ? 0 : 2,
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
vertical: widget.isMobile ? 4 : 8,
|
||||||
|
horizontal: widget.isMobile ? 0 : 8),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(widget.isMobile ? 8 : 12)),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(widget.isMobile ? 8.0 : 12.0),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(opt['name'] ?? '',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold)),
|
||||||
|
if (opt['details'] != null &&
|
||||||
|
opt['details'] != '')
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 2.0),
|
||||||
|
child: Text(opt['details'],
|
||||||
|
style: const TextStyle(fontSize: 13)),
|
||||||
|
),
|
||||||
|
Text('Prix : ${opt['price'] ?? ''} €',
|
||||||
|
style: const TextStyle(fontSize: 13)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.delete),
|
||||||
|
tooltip: 'Supprimer cette option',
|
||||||
|
onPressed: () {
|
||||||
|
if (widget.onRemove != null) {
|
||||||
|
widget.onRemove!(opt['name'] as String);
|
||||||
|
} else {
|
||||||
|
final newList = List<Map<String, dynamic>>.from(
|
||||||
|
widget.selectedOptions)
|
||||||
|
..removeWhere(
|
||||||
|
(o) => o['name'] == opt['name']);
|
||||||
|
widget.onChanged(newList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Center(
|
||||||
|
child: ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Ajouter une option'),
|
||||||
|
onPressed:
|
||||||
|
_loading || widget.eventTypeRequired ? null : _showOptionPicker,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OptionPickerDialog extends StatefulWidget {
|
||||||
|
final List<EventOption> allOptions;
|
||||||
|
final String? eventType;
|
||||||
|
const _OptionPickerDialog(
|
||||||
|
{required this.allOptions, required this.eventType});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_OptionPickerDialog> createState() => _OptionPickerDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _OptionPickerDialogState extends State<_OptionPickerDialog> {
|
||||||
|
String _search = '';
|
||||||
|
bool _creating = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final filtered = widget.allOptions.where((opt) {
|
||||||
|
if (widget.eventType == null) return false;
|
||||||
|
final matchesType =
|
||||||
|
opt.eventTypes.any((ref) => ref.id == widget.eventType);
|
||||||
|
final matchesSearch =
|
||||||
|
opt.name.toLowerCase().contains(_search.toLowerCase());
|
||||||
|
return matchesType && matchesSearch;
|
||||||
|
}).toList();
|
||||||
|
return Dialog(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 400,
|
||||||
|
height: 500,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Rechercher une option',
|
||||||
|
prefixIcon: Icon(Icons.search),
|
||||||
|
),
|
||||||
|
onChanged: (v) => setState(() => _search = v),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: filtered.isEmpty
|
||||||
|
? const Center(
|
||||||
|
child: Text(
|
||||||
|
'Aucune option disponible pour ce type d\'événement.'))
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: filtered.length,
|
||||||
|
itemBuilder: (context, i) {
|
||||||
|
final opt = filtered[i];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(opt.name),
|
||||||
|
subtitle: Text(opt.details +
|
||||||
|
'\nFourchette: ${opt.valMin}€ ~ ${opt.valMax}€'),
|
||||||
|
onTap: () async {
|
||||||
|
final min = opt.valMin;
|
||||||
|
final max = opt.valMax;
|
||||||
|
final defaultPrice =
|
||||||
|
((min + max) / 2).toStringAsFixed(2);
|
||||||
|
final price = await showDialog<double>(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) {
|
||||||
|
final priceController =
|
||||||
|
TextEditingController(text: defaultPrice);
|
||||||
|
return AlertDialog(
|
||||||
|
title: Text('Prix pour ${opt.name}'),
|
||||||
|
content: TextField(
|
||||||
|
controller: priceController,
|
||||||
|
keyboardType:
|
||||||
|
const TextInputType.numberWithOptions(
|
||||||
|
decimal: true),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Prix (€)'),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(ctx),
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
final price = double.tryParse(
|
||||||
|
priceController.text
|
||||||
|
.replaceAll(',', '.')) ??
|
||||||
|
0.0;
|
||||||
|
Navigator.pop(ctx, price);
|
||||||
|
},
|
||||||
|
child: const Text('Ajouter'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (price != null) {
|
||||||
|
Navigator.pop(context, {
|
||||||
|
'name': opt.name,
|
||||||
|
'price': price,
|
||||||
|
'compatibleTypes': opt.eventTypes
|
||||||
|
.map((ref) => ref.id)
|
||||||
|
.toList(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 8.0, top: 4.0),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () async {
|
||||||
|
setState(() => _creating = true);
|
||||||
|
final created = await showDialog<bool>(
|
||||||
|
context: context,
|
||||||
|
builder: (ctx) => _CreateOptionDialog(),
|
||||||
|
);
|
||||||
|
setState(() => _creating = false);
|
||||||
|
if (created == true) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: _creating
|
||||||
|
? const Padding(
|
||||||
|
padding: EdgeInsets.all(8.0),
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
)
|
||||||
|
: const Text(
|
||||||
|
'Ajouter une nouvelle option',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.blue,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CreateOptionDialog extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
State<_CreateOptionDialog> createState() => _CreateOptionDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CreateOptionDialogState extends State<_CreateOptionDialog> {
|
||||||
|
final _formKey = GlobalKey<FormState>();
|
||||||
|
final _nameController = TextEditingController();
|
||||||
|
final _detailsController = TextEditingController();
|
||||||
|
final _minPriceController = TextEditingController();
|
||||||
|
final _maxPriceController = TextEditingController();
|
||||||
|
List<String> _selectedTypes = [];
|
||||||
|
final List<String> _allTypes = ['Bal', 'Mariage', 'Anniversaire'];
|
||||||
|
String? _error;
|
||||||
|
bool _checkingName = false;
|
||||||
|
|
||||||
|
Future<bool> _isNameUnique(String name) async {
|
||||||
|
final snap = await FirebaseFirestore.instance
|
||||||
|
.collection('options')
|
||||||
|
.where('name', isEqualTo: name)
|
||||||
|
.get();
|
||||||
|
return snap.docs.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Créer une nouvelle option'),
|
||||||
|
content: SingleChildScrollView(
|
||||||
|
child: Form(
|
||||||
|
key: _formKey,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
TextFormField(
|
||||||
|
controller: _nameController,
|
||||||
|
decoration:
|
||||||
|
const InputDecoration(labelText: 'Nom de l\'option'),
|
||||||
|
validator: (v) =>
|
||||||
|
v == null || v.isEmpty ? 'Champ requis' : null,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
TextFormField(
|
||||||
|
controller: _detailsController,
|
||||||
|
decoration: const InputDecoration(labelText: 'Détails'),
|
||||||
|
maxLines: 2,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
controller: _minPriceController,
|
||||||
|
decoration:
|
||||||
|
const InputDecoration(labelText: 'Prix min (€)'),
|
||||||
|
keyboardType:
|
||||||
|
const TextInputType.numberWithOptions(decimal: true),
|
||||||
|
validator: (v) =>
|
||||||
|
v == null || v.isEmpty ? 'Obligatoire' : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
controller: _maxPriceController,
|
||||||
|
decoration:
|
||||||
|
const InputDecoration(labelText: 'Prix max (€)'),
|
||||||
|
keyboardType:
|
||||||
|
const TextInputType.numberWithOptions(decimal: true),
|
||||||
|
validator: (v) =>
|
||||||
|
v == null || v.isEmpty ? 'Obligatoire' : null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Types d\'événement associés :'),
|
||||||
|
Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
children: _allTypes
|
||||||
|
.map((type) => FilterChip(
|
||||||
|
label: Text(type),
|
||||||
|
selected: _selectedTypes.contains(type),
|
||||||
|
onSelected: (selected) {
|
||||||
|
setState(() {
|
||||||
|
if (selected) {
|
||||||
|
_selectedTypes.add(type);
|
||||||
|
} else {
|
||||||
|
_selectedTypes.remove(type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (_error != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
|
child:
|
||||||
|
Text(_error!, style: const TextStyle(color: Colors.red)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, false),
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _checkingName
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
if (_selectedTypes.isEmpty) {
|
||||||
|
setState(() =>
|
||||||
|
_error = 'Sélectionnez au moins un type d\'événement');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final min = double.tryParse(
|
||||||
|
_minPriceController.text.replaceAll(',', '.'));
|
||||||
|
final max = double.tryParse(
|
||||||
|
_maxPriceController.text.replaceAll(',', '.'));
|
||||||
|
if (min == null || max == null) {
|
||||||
|
setState(
|
||||||
|
() => _error = 'Prix min et max doivent être valides');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final name = _nameController.text.trim();
|
||||||
|
setState(() => _checkingName = true);
|
||||||
|
final unique = await _isNameUnique(name);
|
||||||
|
setState(() => _checkingName = false);
|
||||||
|
if (!unique) {
|
||||||
|
setState(
|
||||||
|
() => _error = 'Ce nom d\'option est déjà utilisé.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final eventTypeRefs = _selectedTypes
|
||||||
|
.map((type) => FirebaseFirestore.instance
|
||||||
|
.collection('eventTypes')
|
||||||
|
.doc(type))
|
||||||
|
.toList();
|
||||||
|
try {
|
||||||
|
await FirebaseFirestore.instance.collection('options').add({
|
||||||
|
'name': name,
|
||||||
|
'details': _detailsController.text.trim(),
|
||||||
|
'valMin': min,
|
||||||
|
'valMax': max,
|
||||||
|
'eventTypes': eventTypeRefs,
|
||||||
|
});
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
} catch (e) {
|
||||||
|
setState(() => _error = 'Erreur lors de la création : $e');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: _checkingName
|
||||||
|
? const SizedBox(
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2))
|
||||||
|
: const Text('Créer'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -117,7 +117,7 @@ class MainDrawer extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
PermissionGate(
|
PermissionGate(
|
||||||
requiredPermissions: const [Permission.viewUsers],
|
requiredPermissions: const ['view_all_users'],
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: const Icon(Icons.group),
|
leading: const Icon(Icons.group),
|
||||||
title: const Text('Gestion des Utilisateurs'),
|
title: const Text('Gestion des Utilisateurs'),
|
||||||
|
@ -3,6 +3,8 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:em2rp/models/user_model.dart';
|
import 'package:em2rp/models/user_model.dart';
|
||||||
import 'package:em2rp/providers/users_provider.dart';
|
import 'package:em2rp/providers/users_provider.dart';
|
||||||
import 'package:em2rp/utils/colors.dart';
|
import 'package:em2rp/utils/colors.dart';
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:em2rp/models/role_model.dart';
|
||||||
|
|
||||||
class EditUserDialog extends StatefulWidget {
|
class EditUserDialog extends StatefulWidget {
|
||||||
final UserModel user;
|
final UserModel user;
|
||||||
@ -17,9 +19,9 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
late final TextEditingController lastNameController;
|
late final TextEditingController lastNameController;
|
||||||
late final TextEditingController emailController;
|
late final TextEditingController emailController;
|
||||||
late final TextEditingController phoneController;
|
late final TextEditingController phoneController;
|
||||||
String selectedRole = '';
|
String? selectedRoleId;
|
||||||
|
List<RoleModel> availableRoles = [];
|
||||||
static const List<String> roles = ['ADMIN', 'CREW'];
|
bool isLoadingRoles = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -28,7 +30,20 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
lastNameController = TextEditingController(text: widget.user.lastName);
|
lastNameController = TextEditingController(text: widget.user.lastName);
|
||||||
emailController = TextEditingController(text: widget.user.email);
|
emailController = TextEditingController(text: widget.user.email);
|
||||||
phoneController = TextEditingController(text: widget.user.phoneNumber);
|
phoneController = TextEditingController(text: widget.user.phoneNumber);
|
||||||
selectedRole = widget.user.role.isEmpty ? roles.first : widget.user.role;
|
_loadRoles();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadRoles() async {
|
||||||
|
final snapshot = await FirebaseFirestore.instance.collection('roles').get();
|
||||||
|
setState(() {
|
||||||
|
availableRoles = snapshot.docs
|
||||||
|
.map((doc) => RoleModel.fromMap(doc.data(), doc.id))
|
||||||
|
.toList();
|
||||||
|
selectedRoleId = widget.user.role.isEmpty
|
||||||
|
? (availableRoles.isNotEmpty ? availableRoles.first.id : null)
|
||||||
|
: widget.user.role;
|
||||||
|
isLoadingRoles = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -111,24 +126,26 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
keyboardType: TextInputType.phone,
|
keyboardType: TextInputType.phone,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
DropdownButtonFormField<String>(
|
isLoadingRoles
|
||||||
value: selectedRole,
|
? const CircularProgressIndicator()
|
||||||
decoration: _buildInputDecoration(
|
: DropdownButtonFormField<String>(
|
||||||
'Rôle', Icons.admin_panel_settings_outlined),
|
value: selectedRoleId,
|
||||||
items: roles.map((String role) {
|
decoration: _buildInputDecoration(
|
||||||
return DropdownMenuItem<String>(
|
'Rôle', Icons.admin_panel_settings_outlined),
|
||||||
value: role,
|
items: availableRoles.map((role) {
|
||||||
child: Text(role),
|
return DropdownMenuItem<String>(
|
||||||
);
|
value: role.id,
|
||||||
}).toList(),
|
child: Text(role.name),
|
||||||
onChanged: (String? newValue) {
|
);
|
||||||
if (newValue != null) {
|
}).toList(),
|
||||||
setState(() {
|
onChanged: (String? newValue) {
|
||||||
selectedRole = newValue;
|
if (newValue != null) {
|
||||||
});
|
setState(() {
|
||||||
}
|
selectedRoleId = newValue;
|
||||||
},
|
});
|
||||||
),
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -149,16 +166,17 @@ class _EditUserDialogState extends State<EditUserDialog> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
|
if (selectedRoleId == null) return;
|
||||||
final updatedUser = widget.user.copyWith(
|
final updatedUser = widget.user.copyWith(
|
||||||
firstName: firstNameController.text,
|
firstName: firstNameController.text,
|
||||||
lastName: lastNameController.text,
|
lastName: lastNameController.text,
|
||||||
email: emailController.text,
|
email: emailController.text,
|
||||||
phoneNumber: phoneController.text,
|
phoneNumber: phoneController.text,
|
||||||
role: selectedRole,
|
role: selectedRoleId,
|
||||||
);
|
);
|
||||||
Provider.of<UsersProvider>(context, listen: false)
|
await Provider.of<UsersProvider>(context, listen: false)
|
||||||
.updateUser(updatedUser);
|
.updateUser(updatedUser, roleId: selectedRoleId);
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
|
@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:em2rp/models/user_model.dart';
|
import 'package:em2rp/models/user_model.dart';
|
||||||
import 'package:em2rp/utils/colors.dart';
|
import 'package:em2rp/utils/colors.dart';
|
||||||
|
|
||||||
class UserCard extends StatelessWidget {
|
class UserCard extends StatefulWidget {
|
||||||
final UserModel user;
|
final UserModel user;
|
||||||
final VoidCallback onEdit;
|
final VoidCallback onEdit;
|
||||||
final VoidCallback onDelete;
|
final VoidCallback onDelete;
|
||||||
@ -16,6 +16,66 @@ class UserCard extends StatelessWidget {
|
|||||||
required this.onDelete,
|
required this.onDelete,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UserCard> createState() => _UserCardState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserCardState extends State<UserCard> {
|
||||||
|
ImageProvider? _profileImage;
|
||||||
|
String? _lastUrl;
|
||||||
|
bool _isLoadingImage = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(UserCard oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
if (oldWidget.user.profilePhotoUrl != widget.user.profilePhotoUrl) {
|
||||||
|
_loadProfileImage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_loadProfileImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _loadProfileImage() {
|
||||||
|
final url = widget.user.profilePhotoUrl;
|
||||||
|
if (url.isNotEmpty) {
|
||||||
|
setState(() {
|
||||||
|
_isLoadingImage = true;
|
||||||
|
_lastUrl = url;
|
||||||
|
});
|
||||||
|
final image = NetworkImage(url);
|
||||||
|
image.resolve(const ImageConfiguration()).addListener(
|
||||||
|
ImageStreamListener(
|
||||||
|
(info, _) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_profileImage = image;
|
||||||
|
_isLoadingImage = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onError: (error, stack) {
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {
|
||||||
|
_profileImage = null;
|
||||||
|
_isLoadingImage = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_profileImage = null;
|
||||||
|
_isLoadingImage = false;
|
||||||
|
_lastUrl = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final width = MediaQuery.of(context).size.width;
|
final width = MediaQuery.of(context).size.width;
|
||||||
@ -27,7 +87,7 @@ class UserCard extends StatelessWidget {
|
|||||||
elevation: 3,
|
elevation: 3,
|
||||||
child: Container(
|
child: Container(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxWidth: isMobile ? double.infinity : _desktopMaxWidth,
|
maxWidth: isMobile ? double.infinity : UserCard._desktopMaxWidth,
|
||||||
),
|
),
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
child:
|
child:
|
||||||
@ -47,13 +107,13 @@ class UserCard extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"${user.firstName} ${user.lastName}",
|
"${widget.user.firstName} ${widget.user.lastName}",
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(
|
Text(
|
||||||
user.email,
|
widget.user.email,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
@ -65,7 +125,7 @@ class UserCard extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.edit, size: 20),
|
icon: const Icon(Icons.edit, size: 20),
|
||||||
onPressed: onEdit,
|
onPressed: widget.onEdit,
|
||||||
color: AppColors.rouge,
|
color: AppColors.rouge,
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
@ -75,7 +135,7 @@ class UserCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.delete, size: 20),
|
icon: const Icon(Icons.delete, size: 20),
|
||||||
onPressed: onDelete,
|
onPressed: widget.onDelete,
|
||||||
color: AppColors.gris,
|
color: AppColors.gris,
|
||||||
padding: const EdgeInsets.all(8),
|
padding: const EdgeInsets.all(8),
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
@ -106,22 +166,22 @@ class UserCard extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"${user.firstName} ${user.lastName}",
|
"${widget.user.firstName} ${widget.user.lastName}",
|
||||||
style: Theme.of(context).textTheme.titleSmall,
|
style: Theme.of(context).textTheme.titleSmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
user.email,
|
widget.user.email,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
if (user.role.isNotEmpty) ...[
|
if (widget.user.role.isNotEmpty) ...[
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
user.role,
|
widget.user.role,
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
color: AppColors.gris,
|
color: AppColors.gris,
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
@ -143,7 +203,7 @@ class UserCard extends StatelessWidget {
|
|||||||
_buildButton(
|
_buildButton(
|
||||||
icon: Icons.edit,
|
icon: Icons.edit,
|
||||||
label: "Modifier",
|
label: "Modifier",
|
||||||
onPressed: onEdit,
|
onPressed: widget.onEdit,
|
||||||
color: AppColors.rouge,
|
color: AppColors.rouge,
|
||||||
isNarrow: true,
|
isNarrow: true,
|
||||||
),
|
),
|
||||||
@ -151,7 +211,7 @@ class UserCard extends StatelessWidget {
|
|||||||
_buildButton(
|
_buildButton(
|
||||||
icon: Icons.delete,
|
icon: Icons.delete,
|
||||||
label: "Supprimer",
|
label: "Supprimer",
|
||||||
onPressed: onDelete,
|
onPressed: widget.onDelete,
|
||||||
color: AppColors.gris,
|
color: AppColors.gris,
|
||||||
isNarrow: true,
|
isNarrow: true,
|
||||||
),
|
),
|
||||||
@ -163,7 +223,7 @@ class UserCard extends StatelessWidget {
|
|||||||
_buildButton(
|
_buildButton(
|
||||||
icon: Icons.edit,
|
icon: Icons.edit,
|
||||||
label: "Modifier",
|
label: "Modifier",
|
||||||
onPressed: onEdit,
|
onPressed: widget.onEdit,
|
||||||
color: AppColors.rouge,
|
color: AppColors.rouge,
|
||||||
isNarrow: false,
|
isNarrow: false,
|
||||||
),
|
),
|
||||||
@ -171,7 +231,7 @@ class UserCard extends StatelessWidget {
|
|||||||
_buildButton(
|
_buildButton(
|
||||||
icon: Icons.delete,
|
icon: Icons.delete,
|
||||||
label: "Supprimer",
|
label: "Supprimer",
|
||||||
onPressed: onDelete,
|
onPressed: widget.onDelete,
|
||||||
color: AppColors.gris,
|
color: AppColors.gris,
|
||||||
isNarrow: false,
|
isNarrow: false,
|
||||||
),
|
),
|
||||||
@ -218,13 +278,22 @@ class UserCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _profileAvatar(double size) {
|
Widget _profileAvatar(double size) {
|
||||||
|
if (_isLoadingImage && widget.user.profilePhotoUrl.isNotEmpty) {
|
||||||
|
return CircleAvatar(
|
||||||
|
radius: size / 2,
|
||||||
|
backgroundColor: Colors.grey[300],
|
||||||
|
child: SizedBox(
|
||||||
|
width: size * 0.5,
|
||||||
|
height: size * 0.5,
|
||||||
|
child: const CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
return CircleAvatar(
|
return CircleAvatar(
|
||||||
radius: size / 2,
|
radius: size / 2,
|
||||||
backgroundImage: user.profilePhotoUrl.isNotEmpty
|
backgroundImage: _profileImage,
|
||||||
? NetworkImage(user.profilePhotoUrl)
|
|
||||||
: null,
|
|
||||||
backgroundColor: Colors.grey[200],
|
backgroundColor: Colors.grey[200],
|
||||||
child: user.profilePhotoUrl.isEmpty
|
child: (widget.user.profilePhotoUrl.isEmpty || _profileImage == null)
|
||||||
? Icon(Icons.person, size: size * 0.6, color: AppColors.noir)
|
? Icon(Icons.person, size: size * 0.6, color: AppColors.noir)
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
|
@ -0,0 +1,219 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:em2rp/models/user_model.dart';
|
||||||
|
import 'package:em2rp/views/widgets/image/profile_picture.dart';
|
||||||
|
|
||||||
|
class UserMultiSelectWidget extends StatelessWidget {
|
||||||
|
final List<UserModel> allUsers;
|
||||||
|
final List<String> selectedUserIds;
|
||||||
|
final ValueChanged<List<String>> onChanged;
|
||||||
|
final bool isLoading;
|
||||||
|
|
||||||
|
const UserMultiSelectWidget({
|
||||||
|
super.key,
|
||||||
|
required this.allUsers,
|
||||||
|
required this.selectedUserIds,
|
||||||
|
required this.onChanged,
|
||||||
|
this.isLoading = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (isLoading) {
|
||||||
|
return const Center(
|
||||||
|
child:
|
||||||
|
SizedBox(width: 32, height: 32, child: CircularProgressIndicator()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _UserMultiSelect(
|
||||||
|
allUsers: allUsers,
|
||||||
|
selectedUserIds: selectedUserIds,
|
||||||
|
onChanged: onChanged,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserMultiSelect extends StatefulWidget {
|
||||||
|
final List<UserModel> allUsers;
|
||||||
|
final List<String> selectedUserIds;
|
||||||
|
final ValueChanged<List<String>> onChanged;
|
||||||
|
|
||||||
|
const _UserMultiSelect({
|
||||||
|
super.key,
|
||||||
|
required this.allUsers,
|
||||||
|
required this.selectedUserIds,
|
||||||
|
required this.onChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_UserMultiSelect> createState() => _UserMultiSelectState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserMultiSelectState extends State<_UserMultiSelect> {
|
||||||
|
void _openUserPicker() async {
|
||||||
|
final result = await showDialog<List<String>>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => _UserPickerDialog(
|
||||||
|
allUsers: widget.allUsers,
|
||||||
|
initiallySelected: widget.selectedUserIds,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (result != null) {
|
||||||
|
widget.onChanged(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final selectedUsers = widget.allUsers
|
||||||
|
.where((u) => widget.selectedUserIds.contains(u.uid))
|
||||||
|
.toList();
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
UserChipsList(
|
||||||
|
users: selectedUsers,
|
||||||
|
selectedUserIds: widget.selectedUserIds,
|
||||||
|
showRemove: true,
|
||||||
|
onRemove: (uid) {
|
||||||
|
final newList = List<String>.from(widget.selectedUserIds)
|
||||||
|
..remove(uid);
|
||||||
|
widget.onChanged(newList);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Ajouter'),
|
||||||
|
onPressed: _openUserPicker,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserPickerDialog extends StatefulWidget {
|
||||||
|
final List<UserModel> allUsers;
|
||||||
|
final List<String> initiallySelected;
|
||||||
|
const _UserPickerDialog({
|
||||||
|
required this.allUsers,
|
||||||
|
required this.initiallySelected,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_UserPickerDialog> createState() => _UserPickerDialogState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserPickerDialogState extends State<_UserPickerDialog> {
|
||||||
|
String _search = '';
|
||||||
|
late List<String> _selected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_selected = List<String>.from(widget.initiallySelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final filteredUsers = widget.allUsers.where((u) {
|
||||||
|
final query = _search.toLowerCase();
|
||||||
|
return ('${u.firstName} ${u.lastName}').toLowerCase().contains(query);
|
||||||
|
}).toList();
|
||||||
|
return AlertDialog(
|
||||||
|
title: const Text('Ajouter du personnel'),
|
||||||
|
content: SizedBox(
|
||||||
|
width: 400,
|
||||||
|
height: 400,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Rechercher',
|
||||||
|
prefixIcon: Icon(Icons.search),
|
||||||
|
),
|
||||||
|
onChanged: (v) => setState(() => _search = v),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Expanded(
|
||||||
|
child: filteredUsers.isEmpty
|
||||||
|
? const Center(child: Text('Aucun utilisateur trouvé'))
|
||||||
|
: ListView.builder(
|
||||||
|
itemCount: filteredUsers.length,
|
||||||
|
itemBuilder: (context, i) {
|
||||||
|
final user = filteredUsers[i];
|
||||||
|
final isChecked = _selected.contains(user.uid);
|
||||||
|
return CheckboxListTile(
|
||||||
|
value: isChecked,
|
||||||
|
onChanged: (checked) {
|
||||||
|
setState(() {
|
||||||
|
if (checked == true) {
|
||||||
|
_selected.add(user.uid);
|
||||||
|
} else {
|
||||||
|
_selected.remove(user.uid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
title: Text('${user.firstName} ${user.lastName}'),
|
||||||
|
subtitle: Text(user.email),
|
||||||
|
secondary: ProfilePictureWidget(
|
||||||
|
userId: user.uid, radius: 20),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: const Text('Annuler'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Navigator.pop(context, _selected),
|
||||||
|
child: const Text('Ajouter'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserChipsList extends StatelessWidget {
|
||||||
|
final List<UserModel> users;
|
||||||
|
final List<String> selectedUserIds;
|
||||||
|
final ValueChanged<String>? onRemove;
|
||||||
|
final bool showRemove;
|
||||||
|
final double avatarRadius;
|
||||||
|
const UserChipsList({
|
||||||
|
super.key,
|
||||||
|
required this.users,
|
||||||
|
this.selectedUserIds = const [],
|
||||||
|
this.onRemove,
|
||||||
|
this.showRemove = false,
|
||||||
|
this.avatarRadius = 28,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Wrap(
|
||||||
|
spacing: 12,
|
||||||
|
runSpacing: 12,
|
||||||
|
children: users
|
||||||
|
.map((user) => Chip(
|
||||||
|
avatar: ProfilePictureWidget(
|
||||||
|
userId: user.uid, radius: avatarRadius),
|
||||||
|
label: Text('${user.firstName} ${user.lastName}',
|
||||||
|
style: const TextStyle(fontSize: 16)),
|
||||||
|
labelPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
deleteIcon:
|
||||||
|
showRemove ? const Icon(Icons.close, size: 20) : null,
|
||||||
|
onDeleted: showRemove && onRemove != null
|
||||||
|
? () => onRemove!(user.uid)
|
||||||
|
: null,
|
||||||
|
backgroundColor: Colors.grey[200],
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
))
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,172 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:em2rp/models/event_model.dart';
|
|
||||||
import 'package:em2rp/utils/colors.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
|
||||||
|
|
||||||
class EventDetails extends StatelessWidget {
|
|
||||||
final EventModel event;
|
|
||||||
final DateTime? selectedDate;
|
|
||||||
final List<EventModel> events;
|
|
||||||
final void Function(EventModel, DateTime) onSelectEvent;
|
|
||||||
|
|
||||||
const EventDetails({
|
|
||||||
super.key,
|
|
||||||
required this.event,
|
|
||||||
required this.selectedDate,
|
|
||||||
required this.events,
|
|
||||||
required this.onSelectEvent,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final dateFormat = DateFormat('dd/MM/yyyy HH:mm');
|
|
||||||
final currencyFormat = NumberFormat.currency(locale: 'fr_FR', symbol: '€');
|
|
||||||
final fullDateFormat = DateFormat('EEEE d MMMM y', 'fr_FR');
|
|
||||||
// Trie les événements par date de début
|
|
||||||
final sortedEvents = List<EventModel>.from(events)
|
|
||||||
..sort((a, b) => a.startDateTime.compareTo(b.startDateTime));
|
|
||||||
final currentIndex = sortedEvents.indexWhere((e) => e.id == event.id);
|
|
||||||
|
|
||||||
return Card(
|
|
||||||
margin: const EdgeInsets.all(16),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: currentIndex > 0
|
|
||||||
? () {
|
|
||||||
final prevEvent = sortedEvents[currentIndex - 1];
|
|
||||||
onSelectEvent(prevEvent, prevEvent.startDateTime);
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
icon: const Icon(Icons.arrow_back),
|
|
||||||
color: AppColors.rouge,
|
|
||||||
),
|
|
||||||
if (selectedDate != null)
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
fullDateFormat.format(selectedDate!),
|
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
|
||||||
color: AppColors.rouge,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: currentIndex < sortedEvents.length - 1
|
|
||||||
? () {
|
|
||||||
final nextEvent = sortedEvents[currentIndex + 1];
|
|
||||||
onSelectEvent(nextEvent, nextEvent.startDateTime);
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
icon: const Icon(Icons.arrow_forward),
|
|
||||||
color: AppColors.rouge,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
event.name,
|
|
||||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
|
||||||
color: AppColors.noir,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
_buildInfoRow(
|
|
||||||
context,
|
|
||||||
Icons.calendar_today,
|
|
||||||
'Date de début',
|
|
||||||
dateFormat.format(event.startDateTime),
|
|
||||||
),
|
|
||||||
_buildInfoRow(
|
|
||||||
context,
|
|
||||||
Icons.calendar_today,
|
|
||||||
'Date de fin',
|
|
||||||
dateFormat.format(event.endDateTime),
|
|
||||||
),
|
|
||||||
_buildInfoRow(
|
|
||||||
context,
|
|
||||||
Icons.euro,
|
|
||||||
'Prix',
|
|
||||||
currencyFormat.format(event.price),
|
|
||||||
),
|
|
||||||
_buildInfoRow(
|
|
||||||
context,
|
|
||||||
Icons.build,
|
|
||||||
'Temps d\'installation',
|
|
||||||
'${event.installationTime} heures',
|
|
||||||
),
|
|
||||||
_buildInfoRow(
|
|
||||||
context,
|
|
||||||
Icons.construction,
|
|
||||||
'Temps de démontage',
|
|
||||||
'${event.disassemblyTime} heures',
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
'Description',
|
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
|
||||||
color: AppColors.noir,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
event.description,
|
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
'Adresse',
|
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
|
||||||
color: AppColors.noir,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'${event.address.latitude}° N, ${event.address.longitude}° E',
|
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildInfoRow(
|
|
||||||
BuildContext context,
|
|
||||||
IconData icon,
|
|
||||||
String label,
|
|
||||||
String value,
|
|
||||||
) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(icon, color: AppColors.rouge),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Text(
|
|
||||||
'$label : ',
|
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
||||||
color: AppColors.noir,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
value,
|
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
16
em2rp/node_modules/.bin/fxparser
generated
vendored
Normal file
16
em2rp/node_modules/.bin/fxparser
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||||
|
|
||||||
|
case `uname` in
|
||||||
|
*CYGWIN*|*MINGW*|*MSYS*)
|
||||||
|
if command -v cygpath > /dev/null 2>&1; then
|
||||||
|
basedir=`cygpath -w "$basedir"`
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/node" ]; then
|
||||||
|
exec "$basedir/node" "$basedir/../fast-xml-parser/src/cli/cli.js" "$@"
|
||||||
|
else
|
||||||
|
exec node "$basedir/../fast-xml-parser/src/cli/cli.js" "$@"
|
||||||
|
fi
|
17
em2rp/node_modules/.bin/fxparser.cmd
generated
vendored
Normal file
17
em2rp/node_modules/.bin/fxparser.cmd
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@ECHO off
|
||||||
|
GOTO start
|
||||||
|
:find_dp0
|
||||||
|
SET dp0=%~dp0
|
||||||
|
EXIT /b
|
||||||
|
:start
|
||||||
|
SETLOCAL
|
||||||
|
CALL :find_dp0
|
||||||
|
|
||||||
|
IF EXIST "%dp0%\node.exe" (
|
||||||
|
SET "_prog=%dp0%\node.exe"
|
||||||
|
) ELSE (
|
||||||
|
SET "_prog=node"
|
||||||
|
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||||
|
)
|
||||||
|
|
||||||
|
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\fast-xml-parser\src\cli\cli.js" %*
|
28
em2rp/node_modules/.bin/fxparser.ps1
generated
vendored
Normal file
28
em2rp/node_modules/.bin/fxparser.ps1
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||||
|
|
||||||
|
$exe=""
|
||||||
|
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||||
|
# Fix case when both the Windows and Linux builds of Node
|
||||||
|
# are installed in the same directory
|
||||||
|
$exe=".exe"
|
||||||
|
}
|
||||||
|
$ret=0
|
||||||
|
if (Test-Path "$basedir/node$exe") {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "$basedir/node$exe" "$basedir/../fast-xml-parser/src/cli/cli.js" $args
|
||||||
|
} else {
|
||||||
|
& "$basedir/node$exe" "$basedir/../fast-xml-parser/src/cli/cli.js" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
} else {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "node$exe" "$basedir/../fast-xml-parser/src/cli/cli.js" $args
|
||||||
|
} else {
|
||||||
|
& "node$exe" "$basedir/../fast-xml-parser/src/cli/cli.js" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
}
|
||||||
|
exit $ret
|
16
em2rp/node_modules/.bin/mime
generated
vendored
Normal file
16
em2rp/node_modules/.bin/mime
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||||
|
|
||||||
|
case `uname` in
|
||||||
|
*CYGWIN*|*MINGW*|*MSYS*)
|
||||||
|
if command -v cygpath > /dev/null 2>&1; then
|
||||||
|
basedir=`cygpath -w "$basedir"`
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/node" ]; then
|
||||||
|
exec "$basedir/node" "$basedir/../mime/cli.js" "$@"
|
||||||
|
else
|
||||||
|
exec node "$basedir/../mime/cli.js" "$@"
|
||||||
|
fi
|
17
em2rp/node_modules/.bin/mime.cmd
generated
vendored
Normal file
17
em2rp/node_modules/.bin/mime.cmd
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@ECHO off
|
||||||
|
GOTO start
|
||||||
|
:find_dp0
|
||||||
|
SET dp0=%~dp0
|
||||||
|
EXIT /b
|
||||||
|
:start
|
||||||
|
SETLOCAL
|
||||||
|
CALL :find_dp0
|
||||||
|
|
||||||
|
IF EXIST "%dp0%\node.exe" (
|
||||||
|
SET "_prog=%dp0%\node.exe"
|
||||||
|
) ELSE (
|
||||||
|
SET "_prog=node"
|
||||||
|
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||||
|
)
|
||||||
|
|
||||||
|
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\mime\cli.js" %*
|
28
em2rp/node_modules/.bin/mime.ps1
generated
vendored
Normal file
28
em2rp/node_modules/.bin/mime.ps1
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||||
|
|
||||||
|
$exe=""
|
||||||
|
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||||
|
# Fix case when both the Windows and Linux builds of Node
|
||||||
|
# are installed in the same directory
|
||||||
|
$exe=".exe"
|
||||||
|
}
|
||||||
|
$ret=0
|
||||||
|
if (Test-Path "$basedir/node$exe") {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "$basedir/node$exe" "$basedir/../mime/cli.js" $args
|
||||||
|
} else {
|
||||||
|
& "$basedir/node$exe" "$basedir/../mime/cli.js" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
} else {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "node$exe" "$basedir/../mime/cli.js" $args
|
||||||
|
} else {
|
||||||
|
& "node$exe" "$basedir/../mime/cli.js" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
}
|
||||||
|
exit $ret
|
16
em2rp/node_modules/.bin/uuid
generated
vendored
Normal file
16
em2rp/node_modules/.bin/uuid
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
||||||
|
|
||||||
|
case `uname` in
|
||||||
|
*CYGWIN*|*MINGW*|*MSYS*)
|
||||||
|
if command -v cygpath > /dev/null 2>&1; then
|
||||||
|
basedir=`cygpath -w "$basedir"`
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -x "$basedir/node" ]; then
|
||||||
|
exec "$basedir/node" "$basedir/../uuid/dist/bin/uuid" "$@"
|
||||||
|
else
|
||||||
|
exec node "$basedir/../uuid/dist/bin/uuid" "$@"
|
||||||
|
fi
|
17
em2rp/node_modules/.bin/uuid.cmd
generated
vendored
Normal file
17
em2rp/node_modules/.bin/uuid.cmd
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
@ECHO off
|
||||||
|
GOTO start
|
||||||
|
:find_dp0
|
||||||
|
SET dp0=%~dp0
|
||||||
|
EXIT /b
|
||||||
|
:start
|
||||||
|
SETLOCAL
|
||||||
|
CALL :find_dp0
|
||||||
|
|
||||||
|
IF EXIST "%dp0%\node.exe" (
|
||||||
|
SET "_prog=%dp0%\node.exe"
|
||||||
|
) ELSE (
|
||||||
|
SET "_prog=node"
|
||||||
|
SET PATHEXT=%PATHEXT:;.JS;=;%
|
||||||
|
)
|
||||||
|
|
||||||
|
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\uuid\dist\bin\uuid" %*
|
28
em2rp/node_modules/.bin/uuid.ps1
generated
vendored
Normal file
28
em2rp/node_modules/.bin/uuid.ps1
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env pwsh
|
||||||
|
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
|
||||||
|
|
||||||
|
$exe=""
|
||||||
|
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
|
||||||
|
# Fix case when both the Windows and Linux builds of Node
|
||||||
|
# are installed in the same directory
|
||||||
|
$exe=".exe"
|
||||||
|
}
|
||||||
|
$ret=0
|
||||||
|
if (Test-Path "$basedir/node$exe") {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "$basedir/node$exe" "$basedir/../uuid/dist/bin/uuid" $args
|
||||||
|
} else {
|
||||||
|
& "$basedir/node$exe" "$basedir/../uuid/dist/bin/uuid" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
} else {
|
||||||
|
# Support pipeline input
|
||||||
|
if ($MyInvocation.ExpectingInput) {
|
||||||
|
$input | & "node$exe" "$basedir/../uuid/dist/bin/uuid" $args
|
||||||
|
} else {
|
||||||
|
& "node$exe" "$basedir/../uuid/dist/bin/uuid" $args
|
||||||
|
}
|
||||||
|
$ret=$LASTEXITCODE
|
||||||
|
}
|
||||||
|
exit $ret
|
963
em2rp/node_modules/.package-lock.json
generated
vendored
Normal file
963
em2rp/node_modules/.package-lock.json
generated
vendored
Normal file
@ -0,0 +1,963 @@
|
|||||||
|
{
|
||||||
|
"name": "em2rp",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"node_modules/@google-cloud/paginator": {
|
||||||
|
"version": "5.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz",
|
||||||
|
"integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"arrify": "^2.0.0",
|
||||||
|
"extend": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@google-cloud/projectify": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@google-cloud/promisify": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@google-cloud/storage": {
|
||||||
|
"version": "7.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@google-cloud/storage/-/storage-7.16.0.tgz",
|
||||||
|
"integrity": "sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@google-cloud/paginator": "^5.0.0",
|
||||||
|
"@google-cloud/projectify": "^4.0.0",
|
||||||
|
"@google-cloud/promisify": "<4.1.0",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"async-retry": "^1.3.3",
|
||||||
|
"duplexify": "^4.1.3",
|
||||||
|
"fast-xml-parser": "^4.4.1",
|
||||||
|
"gaxios": "^6.0.2",
|
||||||
|
"google-auth-library": "^9.6.3",
|
||||||
|
"html-entities": "^2.5.2",
|
||||||
|
"mime": "^3.0.0",
|
||||||
|
"p-limit": "^3.0.1",
|
||||||
|
"retry-request": "^7.0.0",
|
||||||
|
"teeny-request": "^9.0.0",
|
||||||
|
"uuid": "^8.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tootallnate/once": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/caseless": {
|
||||||
|
"version": "0.12.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
|
||||||
|
"integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "22.15.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz",
|
||||||
|
"integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~6.21.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/request": {
|
||||||
|
"version": "2.48.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz",
|
||||||
|
"integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/caseless": "*",
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/tough-cookie": "*",
|
||||||
|
"form-data": "^2.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/tough-cookie": {
|
||||||
|
"version": "4.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
|
||||||
|
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/abort-controller": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"event-target-shim": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/agent-base": {
|
||||||
|
"version": "7.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
|
||||||
|
"integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/arrify": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/async-retry": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"retry": "0.13.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/base64-js": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/bignumber.js": {
|
||||||
|
"version": "9.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz",
|
||||||
|
"integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/buffer-equal-constant-time": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/call-bind-apply-helpers": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/debug": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "^2.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/dunder-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"gopd": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/duplexify": {
|
||||||
|
"version": "4.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
|
||||||
|
"integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.4.1",
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"readable-stream": "^3.1.1",
|
||||||
|
"stream-shift": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ecdsa-sig-formatter": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||||
|
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-define-property": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-errors": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-object-atoms": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/es-set-tostringtag": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"get-intrinsic": "^1.2.6",
|
||||||
|
"has-tostringtag": "^1.0.2",
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/event-target-shim": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/extend": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/fast-xml-parser": {
|
||||||
|
"version": "4.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz",
|
||||||
|
"integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"strnum": "^1.1.1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"fxparser": "src/cli/cli.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/form-data": {
|
||||||
|
"version": "2.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.3.tgz",
|
||||||
|
"integrity": "sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.8",
|
||||||
|
"es-set-tostringtag": "^2.1.0",
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
|
"safe-buffer": "^5.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/function-bind": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gaxios": {
|
||||||
|
"version": "6.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
|
||||||
|
"integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"https-proxy-agent": "^7.0.1",
|
||||||
|
"is-stream": "^2.0.0",
|
||||||
|
"node-fetch": "^2.6.9",
|
||||||
|
"uuid": "^9.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gaxios/node_modules/uuid": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gcp-metadata": {
|
||||||
|
"version": "6.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.1.tgz",
|
||||||
|
"integrity": "sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"gaxios": "^6.1.1",
|
||||||
|
"google-logging-utils": "^0.0.2",
|
||||||
|
"json-bigint": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-intrinsic": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"call-bind-apply-helpers": "^1.0.2",
|
||||||
|
"es-define-property": "^1.0.1",
|
||||||
|
"es-errors": "^1.3.0",
|
||||||
|
"es-object-atoms": "^1.1.1",
|
||||||
|
"function-bind": "^1.1.2",
|
||||||
|
"get-proto": "^1.0.1",
|
||||||
|
"gopd": "^1.2.0",
|
||||||
|
"has-symbols": "^1.1.0",
|
||||||
|
"hasown": "^2.0.2",
|
||||||
|
"math-intrinsics": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-proto": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"dunder-proto": "^1.0.1",
|
||||||
|
"es-object-atoms": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/google-auth-library": {
|
||||||
|
"version": "9.15.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.1.tgz",
|
||||||
|
"integrity": "sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.3.0",
|
||||||
|
"ecdsa-sig-formatter": "^1.0.11",
|
||||||
|
"gaxios": "^6.1.1",
|
||||||
|
"gcp-metadata": "^6.1.0",
|
||||||
|
"gtoken": "^7.0.0",
|
||||||
|
"jws": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/google-logging-utils": {
|
||||||
|
"version": "0.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/google-logging-utils/-/google-logging-utils-0.0.2.tgz",
|
||||||
|
"integrity": "sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gopd": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/gtoken": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"gaxios": "^6.0.0",
|
||||||
|
"jws": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-symbols": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/has-tostringtag": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-symbols": "^1.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/hasown": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"function-bind": "^1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/html-entities": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/mdevils"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://patreon.com/mdevils"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/http-proxy-agent": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@tootallnate/once": "2",
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/http-proxy-agent/node_modules/agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/https-proxy-agent": {
|
||||||
|
"version": "7.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||||
|
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "^7.1.2",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/is-stream": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/json-bigint": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"bignumber.js": "^9.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jwa": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-equal-constant-time": "^1.0.1",
|
||||||
|
"ecdsa-sig-formatter": "1.0.11",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jws": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"jwa": "^2.0.0",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/math-intrinsics": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mime": "cli.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-db": {
|
||||||
|
"version": "1.52.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||||
|
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/mime-types": {
|
||||||
|
"version": "2.1.35",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||||
|
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"mime-db": "1.52.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/p-limit": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"yocto-queue": "^0.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/retry": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/retry-request": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/request": "^2.48.8",
|
||||||
|
"extend": "^3.0.2",
|
||||||
|
"teeny-request": "^9.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/safe-buffer": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/stream-events": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"stubs": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/stream-shift": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strnum": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/NaturalIntelligence"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/stubs": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/teeny-request": {
|
||||||
|
"version": "9.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz",
|
||||||
|
"integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"http-proxy-agent": "^5.0.0",
|
||||||
|
"https-proxy-agent": "^5.0.0",
|
||||||
|
"node-fetch": "^2.6.9",
|
||||||
|
"stream-events": "^1.0.5",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/teeny-request/node_modules/agent-base": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/teeny-request/node_modules/https-proxy-agent": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"agent-base": "6",
|
||||||
|
"debug": "4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/teeny-request/node_modules/uuid": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/undici-types": {
|
||||||
|
"version": "6.21.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||||
|
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
|
||||||
|
"license": "BSD-2-Clause"
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/yocto-queue": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
262
em2rp/node_modules/@google-cloud/paginator/CHANGELOG.md
generated
vendored
Normal file
262
em2rp/node_modules/@google-cloud/paginator/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
[npm history][1]
|
||||||
|
|
||||||
|
[1]: https://www.npmjs.com/package/nodejs-paginator?activeTab=versions
|
||||||
|
|
||||||
|
## [5.0.2](https://github.com/googleapis/nodejs-paginator/compare/v5.0.1...v5.0.2) (2024-05-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Query should be on the list of extra args ([#365](https://github.com/googleapis/nodejs-paginator/issues/365)) ([50e40d0](https://github.com/googleapis/nodejs-paginator/commit/50e40d064aed1bd0d5f93a51ad54112343086644))
|
||||||
|
|
||||||
|
## [5.0.1](https://github.com/googleapis/nodejs-paginator/compare/v5.0.0...v5.0.1) (2024-05-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Should pass extra callback arguments back to consumer ([#361](https://github.com/googleapis/nodejs-paginator/issues/361)) ([cc5c48b](https://github.com/googleapis/nodejs-paginator/commit/cc5c48b95b21e9c6a4e555ff98de267258657b6e))
|
||||||
|
|
||||||
|
## [5.0.0](https://github.com/googleapis/nodejs-paginator/compare/v4.0.1...v5.0.0) (2023-08-09)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* update to Node 14 ([#346](https://github.com/googleapis/nodejs-paginator/issues/346))
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* Update to Node 14 ([#346](https://github.com/googleapis/nodejs-paginator/issues/346)) ([262ad70](https://github.com/googleapis/nodejs-paginator/commit/262ad70d3cc5e1aa8a67ece54c04920b24ceea09))
|
||||||
|
|
||||||
|
## [4.0.1](https://github.com/googleapis/nodejs-paginator/compare/v4.0.0...v4.0.1) (2022-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Remove pip install statements ([#1546](https://github.com/googleapis/nodejs-paginator/issues/1546)) ([#329](https://github.com/googleapis/nodejs-paginator/issues/329)) ([697567b](https://github.com/googleapis/nodejs-paginator/commit/697567bdd86226b740304734b9562a2f2241a96f))
|
||||||
|
|
||||||
|
## [4.0.0](https://github.com/googleapis/nodejs-paginator/compare/v3.0.7...v4.0.0) (2022-05-17)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* update library to use Node 12 (#325)
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* update library to use Node 12 ([#325](https://github.com/googleapis/nodejs-paginator/issues/325)) ([02887ae](https://github.com/googleapis/nodejs-paginator/commit/02887ae2b370bff18cae7fe1d434ecdf663b5748))
|
||||||
|
|
||||||
|
### [3.0.7](https://github.com/googleapis/nodejs-paginator/compare/v3.0.6...v3.0.7) (2022-02-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* update signature of end to comply with update node types definition ([#311](https://github.com/googleapis/nodejs-paginator/issues/311)) ([79e6fbd](https://github.com/googleapis/nodejs-paginator/commit/79e6fbdae5008d874613d2919a6cf723708fc919))
|
||||||
|
|
||||||
|
### [3.0.6](https://www.github.com/googleapis/nodejs-paginator/compare/v3.0.5...v3.0.6) (2021-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **build:** switch primary branch to main ([#287](https://www.github.com/googleapis/nodejs-paginator/issues/287)) ([1b796f3](https://www.github.com/googleapis/nodejs-paginator/commit/1b796f3377174354a62b7475d16f52213197f650))
|
||||||
|
|
||||||
|
### [3.0.5](https://www.github.com/googleapis/nodejs-paginator/compare/v3.0.4...v3.0.5) (2020-09-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add configs by running synthtool ([#241](https://www.github.com/googleapis/nodejs-paginator/issues/241)) ([643593a](https://www.github.com/googleapis/nodejs-paginator/commit/643593ae9ffb8febff69a7bdae19239f5bcb1266))
|
||||||
|
|
||||||
|
### [3.0.4](https://www.github.com/googleapis/nodejs-paginator/compare/v3.0.3...v3.0.4) (2020-08-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* destroy ResourceStream with pre-flight error ([#236](https://www.github.com/googleapis/nodejs-paginator/issues/236)) ([d57beb4](https://www.github.com/googleapis/nodejs-paginator/commit/d57beb424d875a7bf502d458cc208f1bbe47a42a))
|
||||||
|
|
||||||
|
### [3.0.3](https://www.github.com/googleapis/nodejs-paginator/compare/v3.0.2...v3.0.3) (2020-07-24)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* move gitattributes files to node templates ([#234](https://www.github.com/googleapis/nodejs-paginator/issues/234)) ([30e881c](https://www.github.com/googleapis/nodejs-paginator/commit/30e881ce7415749b93b6b7e4e71745ea3fb248b6))
|
||||||
|
|
||||||
|
### [3.0.2](https://www.github.com/googleapis/nodejs-paginator/compare/v3.0.1...v3.0.2) (2020-07-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* update node issue template ([#221](https://www.github.com/googleapis/nodejs-paginator/issues/221)) ([088153c](https://www.github.com/googleapis/nodejs-paginator/commit/088153c4fca6d53e2e5ef4bb42365ce5493b913d))
|
||||||
|
|
||||||
|
### [3.0.1](https://www.github.com/googleapis/nodejs-paginator/compare/v3.0.0...v3.0.1) (2020-05-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* apache license URL ([#468](https://www.github.com/googleapis/nodejs-paginator/issues/468)) ([#211](https://www.github.com/googleapis/nodejs-paginator/issues/211)) ([f343b7f](https://www.github.com/googleapis/nodejs-paginator/commit/f343b7f7e184fd1b453f20ac1463d17520aac7ad))
|
||||||
|
|
||||||
|
## [3.0.0](https://www.github.com/googleapis/nodejs-paginator/compare/v2.0.3...v3.0.0) (2020-03-25)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* **dep:** upgrade gts 2.0.0 (#194)
|
||||||
|
* **deps:** deprecated node 8 to 10; upgrade typescript
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* **dep:** upgrade gts 2.0.0 ([#194](https://www.github.com/googleapis/nodejs-paginator/issues/194)) ([4eaf9be](https://www.github.com/googleapis/nodejs-paginator/commit/4eaf9bed1fcfd0f10e877ff15c1d0e968e3356c8))
|
||||||
|
* **deps:** deprecated node 8 to 10; upgrade typescript ([f6434ab](https://www.github.com/googleapis/nodejs-paginator/commit/f6434ab9cacb6ab804c070f19c38b6072ca326b5))
|
||||||
|
|
||||||
|
### [2.0.3](https://www.github.com/googleapis/nodejs-paginator/compare/v2.0.2...v2.0.3) (2019-12-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** pin TypeScript below 3.7.0 ([e06e1b0](https://www.github.com/googleapis/nodejs-paginator/commit/e06e1b0a2e2bb1cf56fc806c1703b8b5e468b954))
|
||||||
|
|
||||||
|
### [2.0.2](https://www.github.com/googleapis/nodejs-paginator/compare/v2.0.1...v2.0.2) (2019-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** add jsdoc-region-tag plugin ([#155](https://www.github.com/googleapis/nodejs-paginator/issues/155)) ([b983799](https://www.github.com/googleapis/nodejs-paginator/commit/b98379905848fd179c6268aff3e1cfaf2bf76663))
|
||||||
|
|
||||||
|
### [2.0.1](https://www.github.com/googleapis/nodejs-paginator/compare/v2.0.0...v2.0.1) (2019-08-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** use the latest extend ([#141](https://www.github.com/googleapis/nodejs-paginator/issues/141)) ([61b383e](https://www.github.com/googleapis/nodejs-paginator/commit/61b383e))
|
||||||
|
|
||||||
|
## [2.0.0](https://www.github.com/googleapis/nodejs-paginator/compare/v1.0.2...v2.0.0) (2019-07-12)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* rewrite streaming logic (#136)
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* rewrite streaming logic ([#136](https://www.github.com/googleapis/nodejs-paginator/issues/136)) ([641d82d](https://www.github.com/googleapis/nodejs-paginator/commit/641d82d))
|
||||||
|
|
||||||
|
### [1.0.2](https://www.github.com/googleapis/nodejs-paginator/compare/v1.0.1...v1.0.2) (2019-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** link to reference docs section on googleapis.dev ([#132](https://www.github.com/googleapis/nodejs-paginator/issues/132)) ([be231be](https://www.github.com/googleapis/nodejs-paginator/commit/be231be))
|
||||||
|
|
||||||
|
### [1.0.1](https://www.github.com/googleapis/nodejs-paginator/compare/v1.0.0...v1.0.1) (2019-06-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** move to new client docs URL ([#129](https://www.github.com/googleapis/nodejs-paginator/issues/129)) ([689f483](https://www.github.com/googleapis/nodejs-paginator/commit/689f483))
|
||||||
|
|
||||||
|
## [1.0.0](https://www.github.com/googleapis/nodejs-paginator/compare/v0.2.0...v1.0.0) (2019-05-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** update dependency arrify to v2 ([#109](https://www.github.com/googleapis/nodejs-paginator/issues/109)) ([9f06c83](https://www.github.com/googleapis/nodejs-paginator/commit/9f06c83))
|
||||||
|
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* upgrade engines field to >=8.10.0 ([#115](https://www.github.com/googleapis/nodejs-paginator/issues/115)) ([0921076](https://www.github.com/googleapis/nodejs-paginator/commit/0921076))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* upgrade engines field to >=8.10.0 (#115)
|
||||||
|
|
||||||
|
## v0.2.0
|
||||||
|
|
||||||
|
03-08-2019 12:15 PST
|
||||||
|
|
||||||
|
### New Features
|
||||||
|
- feat: handle promise based functions ([#91](https://github.com/googleapis/nodejs-paginator/pull/91))
|
||||||
|
- refactor(ts): create generic for object streams ([#101](https://github.com/googleapis/nodejs-paginator/pull/101))
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- chore(deps): update dependency through2 to v3 ([#53](https://github.com/googleapis/nodejs-paginator/pull/53))
|
||||||
|
- chore(deps): update dependency @types/is to v0.0.21 ([#55](https://github.com/googleapis/nodejs-paginator/pull/55))
|
||||||
|
- chore(deps): update dependency gts to ^0.9.0 ([#57](https://github.com/googleapis/nodejs-paginator/pull/57))
|
||||||
|
- fix: Pin @types/sinon to last compatible version ([#61](https://github.com/googleapis/nodejs-paginator/pull/61))
|
||||||
|
- refactor: trim a few dependencies ([#60](https://github.com/googleapis/nodejs-paginator/pull/60))
|
||||||
|
- chore(deps): update dependency @types/sinon to v5.0.7 ([#62](https://github.com/googleapis/nodejs-paginator/pull/62))
|
||||||
|
- chore(deps): update dependency @types/sinon to v7 ([#81](https://github.com/googleapis/nodejs-paginator/pull/81))
|
||||||
|
- chore(deps): update dependency mocha to v6
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- docs: add lint/fix example to contributing guide ([#85](https://github.com/googleapis/nodejs-paginator/pull/85))
|
||||||
|
- chore: move CONTRIBUTING.md to root ([#87](https://github.com/googleapis/nodejs-paginator/pull/87))
|
||||||
|
- docs: update links in contrib guide ([#94](https://github.com/googleapis/nodejs-paginator/pull/94))
|
||||||
|
- docs: update contributing path in README ([#88](https://github.com/googleapis/nodejs-paginator/pull/88))
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- chore: include build in eslintignore ([#49](https://github.com/googleapis/nodejs-paginator/pull/49))
|
||||||
|
- chore: update CircleCI config ([#52](https://github.com/googleapis/nodejs-paginator/pull/52))
|
||||||
|
- chore: use latest npm on Windows ([#54](https://github.com/googleapis/nodejs-paginator/pull/54))
|
||||||
|
- chore: update eslintignore config ([#56](https://github.com/googleapis/nodejs-paginator/pull/56))
|
||||||
|
- chore: add synth.metadata
|
||||||
|
- fix(build): fix system key decryption ([#64](https://github.com/googleapis/nodejs-paginator/pull/64))
|
||||||
|
- chore: update license file ([#68](https://github.com/googleapis/nodejs-paginator/pull/68))
|
||||||
|
- chore(build): update prettier config ([#69](https://github.com/googleapis/nodejs-paginator/pull/69))
|
||||||
|
- chore: nyc ignore build/test by default ([#71](https://github.com/googleapis/nodejs-paginator/pull/71))
|
||||||
|
- chore: always nyc report before calling codecov ([#72](https://github.com/googleapis/nodejs-paginator/pull/72))
|
||||||
|
- build: add Kokoro configs for autorelease ([#75](https://github.com/googleapis/nodejs-paginator/pull/75))
|
||||||
|
- fix(build): fix Kokoro release script ([#76](https://github.com/googleapis/nodejs-paginator/pull/76))
|
||||||
|
- chore: fix publish.sh permission +x ([#77](https://github.com/googleapis/nodejs-paginator/pull/77))
|
||||||
|
- chore: update nyc and eslint configs ([#79](https://github.com/googleapis/nodejs-paginator/pull/79))
|
||||||
|
- chore(build): inject yoshi automation key ([#80](https://github.com/googleapis/nodejs-paginator/pull/80))
|
||||||
|
- build: check broken links in generated docs ([#82](https://github.com/googleapis/nodejs-paginator/pull/82))
|
||||||
|
- build: ignore googleapis.com in doc link check ([#84](https://github.com/googleapis/nodejs-paginator/pull/84))
|
||||||
|
- build: test using @grpc/grpc-js in CI ([#89](https://github.com/googleapis/nodejs-paginator/pull/89))
|
||||||
|
- build: create docs test npm scripts ([#90](https://github.com/googleapis/nodejs-paginator/pull/90))
|
||||||
|
- build: use linkinator for docs test ([#93](https://github.com/googleapis/nodejs-paginator/pull/93))
|
||||||
|
- build: update release configuration
|
||||||
|
- build: fix types for sinon ([#98](https://github.com/googleapis/nodejs-paginator/pull/98))
|
||||||
|
- build: use node10 to run samples-test, system-test etc ([#97](https://github.com/googleapis/nodejs-paginator/pull/97))
|
||||||
|
- build: Add docuploader credentials to node publish jobs ([#99](https://github.com/googleapis/nodejs-paginator/pull/99))
|
||||||
|
|
||||||
|
## v0.1.2
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
- fix: call limiter.makeRequest() instead of original method ([#43](https://github.com/googleapis/nodejs-paginator/pull/43))
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- chore: update issue templates ([#42](https://github.com/googleapis/nodejs-paginator/pull/42))
|
||||||
|
- chore: remove old issue template ([#40](https://github.com/googleapis/nodejs-paginator/pull/40))
|
||||||
|
- build: run tests on node11 ([#39](https://github.com/googleapis/nodejs-paginator/pull/39))
|
||||||
|
- chores(build): run codecov on continuous builds ([#36](https://github.com/googleapis/nodejs-paginator/pull/36))
|
||||||
|
- chores(build): do not collect sponge.xml from windows builds ([#37](https://github.com/googleapis/nodejs-paginator/pull/37))
|
||||||
|
- chore: update new issue template ([#35](https://github.com/googleapis/nodejs-paginator/pull/35))
|
||||||
|
- chore(deps): update dependency sinon to v7 ([#31](https://github.com/googleapis/nodejs-paginator/pull/31))
|
||||||
|
- build: fix codecov uploading on Kokoro ([#32](https://github.com/googleapis/nodejs-paginator/pull/32))
|
||||||
|
- Update kokoro config ([#29](https://github.com/googleapis/nodejs-paginator/pull/29))
|
||||||
|
- Update CI config ([#27](https://github.com/googleapis/nodejs-paginator/pull/27))
|
||||||
|
- Don't publish sourcemaps ([#25](https://github.com/googleapis/nodejs-paginator/pull/25))
|
||||||
|
- build: prevent system/sample-test from leaking credentials
|
||||||
|
- Update kokoro config ([#23](https://github.com/googleapis/nodejs-paginator/pull/23))
|
||||||
|
- test: remove appveyor config ([#22](https://github.com/googleapis/nodejs-paginator/pull/22))
|
||||||
|
- Update CI config ([#21](https://github.com/googleapis/nodejs-paginator/pull/21))
|
||||||
|
- Enable prefer-const in the eslint config ([#20](https://github.com/googleapis/nodejs-paginator/pull/20))
|
||||||
|
- Enable no-var in eslint ([#19](https://github.com/googleapis/nodejs-paginator/pull/19))
|
||||||
|
- Update CI config ([#18](https://github.com/googleapis/nodejs-paginator/pull/18))
|
||||||
|
|
||||||
|
## v0.1.1
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- Add synth script and update CI config (#14)
|
||||||
|
- chore(deps): update dependency nyc to v13 (#12)
|
||||||
|
- chore: ignore package-lock.json (#11)
|
||||||
|
- chore(deps): lock file maintenance (#10)
|
||||||
|
- chore: update renovate config (#9)
|
||||||
|
- remove that whitespace (#8)
|
||||||
|
- chore(deps): lock file maintenance (#7)
|
||||||
|
- chore(deps): update dependency typescript to v3 (#6)
|
||||||
|
- chore: assert.deelEqual => assert.deepStrictEqual (#5)
|
||||||
|
- chore: move mocha options to mocha.opts (#4)
|
202
em2rp/node_modules/@google-cloud/paginator/LICENSE
generated
vendored
Normal file
202
em2rp/node_modules/@google-cloud/paginator/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
136
em2rp/node_modules/@google-cloud/paginator/README.md
generated
vendored
Normal file
136
em2rp/node_modules/@google-cloud/paginator/README.md
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
[//]: # "This README.md file is auto-generated, all changes to this file will be lost."
|
||||||
|
[//]: # "To regenerate it, use `python -m synthtool`."
|
||||||
|
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
|
||||||
|
|
||||||
|
# [Google Cloud Common Paginator: Node.js Client](https://github.com/googleapis/nodejs-paginator)
|
||||||
|
|
||||||
|
[](https://cloud.google.com/terms/launch-stages)
|
||||||
|
[](https://www.npmjs.org/package/@google-cloud/paginator)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A result paging utility used by Google node.js modules
|
||||||
|
|
||||||
|
|
||||||
|
A comprehensive list of changes in each version may be found in
|
||||||
|
[the CHANGELOG](https://github.com/googleapis/nodejs-paginator/blob/main/CHANGELOG.md).
|
||||||
|
|
||||||
|
* [Google Cloud Common Paginator Node.js Client API Reference][client-docs]
|
||||||
|
|
||||||
|
* [github.com/googleapis/nodejs-paginator](https://github.com/googleapis/nodejs-paginator)
|
||||||
|
|
||||||
|
Read more about the client libraries for Cloud APIs, including the older
|
||||||
|
Google APIs Client Libraries, in [Client Libraries Explained][explained].
|
||||||
|
|
||||||
|
[explained]: https://cloud.google.com/apis/docs/client-libraries-explained
|
||||||
|
|
||||||
|
**Table of contents:**
|
||||||
|
|
||||||
|
|
||||||
|
* [Quickstart](#quickstart)
|
||||||
|
|
||||||
|
* [Installing the client library](#installing-the-client-library)
|
||||||
|
* [Using the client library](#using-the-client-library)
|
||||||
|
* [Samples](#samples)
|
||||||
|
* [Versioning](#versioning)
|
||||||
|
* [Contributing](#contributing)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
### Installing the client library
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @google-cloud/paginator
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Using the client library
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const {paginator} = require('@google-cloud/paginator');
|
||||||
|
console.log(paginator);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Samples
|
||||||
|
|
||||||
|
Samples are in the [`samples/`](https://github.com/googleapis/nodejs-paginator/tree/main/samples) directory. Each sample's `README.md` has instructions for running its sample.
|
||||||
|
|
||||||
|
| Sample | Source Code | Try it |
|
||||||
|
| --------------------------- | --------------------------------- | ------ |
|
||||||
|
| Quickstart | [source code](https://github.com/googleapis/nodejs-paginator/blob/main/samples/quickstart.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-paginator&page=editor&open_in_editor=samples/quickstart.js,samples/README.md) |
|
||||||
|
| Streamify | [source code](https://github.com/googleapis/nodejs-paginator/blob/main/samples/streamify.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-paginator&page=editor&open_in_editor=samples/streamify.js,samples/README.md) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The [Google Cloud Common Paginator Node.js Client API Reference][client-docs] documentation
|
||||||
|
also contains samples.
|
||||||
|
|
||||||
|
## Supported Node.js Versions
|
||||||
|
|
||||||
|
Our client libraries follow the [Node.js release schedule](https://github.com/nodejs/release#release-schedule).
|
||||||
|
Libraries are compatible with all current _active_ and _maintenance_ versions of
|
||||||
|
Node.js.
|
||||||
|
If you are using an end-of-life version of Node.js, we recommend that you update
|
||||||
|
as soon as possible to an actively supported LTS version.
|
||||||
|
|
||||||
|
Google's client libraries support legacy versions of Node.js runtimes on a
|
||||||
|
best-efforts basis with the following warnings:
|
||||||
|
|
||||||
|
* Legacy versions are not tested in continuous integration.
|
||||||
|
* Some security patches and features cannot be backported.
|
||||||
|
* Dependencies cannot be kept up-to-date.
|
||||||
|
|
||||||
|
Client libraries targeting some end-of-life versions of Node.js are available, and
|
||||||
|
can be installed through npm [dist-tags](https://docs.npmjs.com/cli/dist-tag).
|
||||||
|
The dist-tags follow the naming convention `legacy-(version)`.
|
||||||
|
For example, `npm install @google-cloud/paginator@legacy-8` installs client libraries
|
||||||
|
for versions compatible with Node.js 8.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
This library follows [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This library is considered to be **stable**. The code surface will not change in backwards-incompatible ways
|
||||||
|
unless absolutely necessary (e.g. because of critical security issues) or with
|
||||||
|
an extensive deprecation period. Issues and requests against **stable** libraries
|
||||||
|
are addressed with the highest priority.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
More Information: [Google Cloud Platform Launch Stages][launch_stages]
|
||||||
|
|
||||||
|
[launch_stages]: https://cloud.google.com/terms/launch-stages
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions welcome! See the [Contributing Guide](https://github.com/googleapis/nodejs-paginator/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
Please note that this `README.md`, the `samples/README.md`,
|
||||||
|
and a variety of configuration files in this repository (including `.nycrc` and `tsconfig.json`)
|
||||||
|
are generated from a central template. To edit one of these files, make an edit
|
||||||
|
to its templates in
|
||||||
|
[directory](https://github.com/googleapis/synthtool).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache Version 2.0
|
||||||
|
|
||||||
|
See [LICENSE](https://github.com/googleapis/nodejs-paginator/blob/main/LICENSE)
|
||||||
|
|
||||||
|
[client-docs]: https://cloud.google.com/nodejs/docs/reference/paginator/latest
|
||||||
|
|
||||||
|
[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
|
||||||
|
[projects]: https://console.cloud.google.com/project
|
||||||
|
[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
|
||||||
|
|
||||||
|
[auth]: https://cloud.google.com/docs/authentication/getting-started
|
57
em2rp/node_modules/@google-cloud/paginator/package.json
generated
vendored
Normal file
57
em2rp/node_modules/@google-cloud/paginator/package.json
generated
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"name": "@google-cloud/paginator",
|
||||||
|
"version": "5.0.2",
|
||||||
|
"description": "A result paging utility used by Google node.js modules",
|
||||||
|
"main": "build/src/index.js",
|
||||||
|
"types": "build/src/index.d.ts",
|
||||||
|
"repository": "googleapis/nodejs-paginator",
|
||||||
|
"scripts": {
|
||||||
|
"test": "c8 mocha build/test",
|
||||||
|
"compile": "tsc -p .",
|
||||||
|
"fix": "gts fix",
|
||||||
|
"prelint": "cd samples; npm link ../; npm install",
|
||||||
|
"lint": "gts check",
|
||||||
|
"prepare": "npm run compile",
|
||||||
|
"pretest": "npm run compile",
|
||||||
|
"docs": "compodoc src/",
|
||||||
|
"presystem-test": "npm run compile",
|
||||||
|
"samples-test": "cd samples/ && npm link ../ && npm test && cd ../",
|
||||||
|
"system-test": "mocha build/system-test",
|
||||||
|
"docs-test": "linkinator docs",
|
||||||
|
"predocs-test": "npm run docs",
|
||||||
|
"clean": "gts clean",
|
||||||
|
"precompile": "gts clean"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"files": [
|
||||||
|
"build/src",
|
||||||
|
"!build/src/**/*.map"
|
||||||
|
],
|
||||||
|
"author": "Google Inc.",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@compodoc/compodoc": "1.1.23",
|
||||||
|
"@types/extend": "^3.0.0",
|
||||||
|
"@types/mocha": "^9.0.0",
|
||||||
|
"@types/node": "^20.4.9",
|
||||||
|
"@types/proxyquire": "^1.3.28",
|
||||||
|
"@types/sinon": "^17.0.0",
|
||||||
|
"@types/uuid": "^9.0.0",
|
||||||
|
"c8": "^9.0.0",
|
||||||
|
"codecov": "^3.0.4",
|
||||||
|
"gts": "^5.0.0",
|
||||||
|
"linkinator": "^4.0.0",
|
||||||
|
"mocha": "^9.2.2",
|
||||||
|
"proxyquire": "^2.0.1",
|
||||||
|
"sinon": "^17.0.0",
|
||||||
|
"typescript": "^5.1.6",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"arrify": "^2.0.0",
|
||||||
|
"extend": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
}
|
196
em2rp/node_modules/@google-cloud/projectify/CHANGELOG.md
generated
vendored
Normal file
196
em2rp/node_modules/@google-cloud/projectify/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
[npm history][1]
|
||||||
|
|
||||||
|
[1]: https://www.npmjs.com/package/@google-cloud/projectify?activeTab=versions
|
||||||
|
## [4.0.0](https://github.com/googleapis/nodejs-projectify/compare/v3.0.0...v4.0.0) (2023-08-09)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* upgrade to Node 14 ([#318](https://github.com/googleapis/nodejs-projectify/issues/318))
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Remove pip install statements ([#1546](https://github.com/googleapis/nodejs-projectify/issues/1546)) ([#304](https://github.com/googleapis/nodejs-projectify/issues/304)) ([94cfff6](https://github.com/googleapis/nodejs-projectify/commit/94cfff665b7c6b8916b5c59e1c7a3cca7ff29303))
|
||||||
|
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* Upgrade to Node 14 ([#318](https://github.com/googleapis/nodejs-projectify/issues/318)) ([6e9da4d](https://github.com/googleapis/nodejs-projectify/commit/6e9da4db77fab7ed6876e755a72156960b376d57))
|
||||||
|
|
||||||
|
## [3.0.0](https://github.com/googleapis/nodejs-projectify/compare/v2.1.1...v3.0.0) (2022-05-20)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* update library to use Node 12 (#299)
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* update library to use Node 12 ([#299](https://github.com/googleapis/nodejs-projectify/issues/299)) ([83b63ca](https://github.com/googleapis/nodejs-projectify/commit/83b63ca8cb89086a8535a9fc8abd39e95f0cecd4))
|
||||||
|
|
||||||
|
### [2.1.1](https://www.github.com/googleapis/nodejs-projectify/compare/v2.1.0...v2.1.1) (2021-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **build:** switch primary branch to main ([#267](https://www.github.com/googleapis/nodejs-projectify/issues/267)) ([9e8d6e4](https://www.github.com/googleapis/nodejs-projectify/commit/9e8d6e48c080806b42164d7be0bd11197996f245))
|
||||||
|
|
||||||
|
## [2.1.0](https://www.github.com/googleapis/nodejs-projectify/compare/v2.0.1...v2.1.0) (2021-06-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `gcf-owl-bot[bot]` to `ignoreAuthors` ([#245](https://www.github.com/googleapis/nodejs-projectify/issues/245)) ([30f0499](https://www.github.com/googleapis/nodejs-projectify/commit/30f0499ade5f140774c3aa672b44fd3538e72309))
|
||||||
|
|
||||||
|
### [2.0.1](https://www.github.com/googleapis/nodejs-projectify/compare/v2.0.0...v2.0.1) (2020-07-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* update node issue template ([#197](https://www.github.com/googleapis/nodejs-projectify/issues/197)) ([3406f2a](https://www.github.com/googleapis/nodejs-projectify/commit/3406f2aa431ed04541585b63c330c04270c602aa))
|
||||||
|
|
||||||
|
## [2.0.0](https://www.github.com/googleapis/nodejs-projectify/compare/v1.0.4...v2.0.0) (2020-03-24)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* typescript@3.7 introduced some breaking changes
|
||||||
|
* drop Node 8 from engines field (#172)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* drop Node 8 from engines field ([#172](https://www.github.com/googleapis/nodejs-projectify/issues/172)) ([3eac424](https://www.github.com/googleapis/nodejs-projectify/commit/3eac424bfb1ee47144a77888dc68db687988945e))
|
||||||
|
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* update to latest version of gts/typescript ([#171](https://www.github.com/googleapis/nodejs-projectify/issues/171)) ([30f90cc](https://www.github.com/googleapis/nodejs-projectify/commit/30f90cc172da6ed9394da91869556bf5eef42434))
|
||||||
|
|
||||||
|
### [1.0.4](https://www.github.com/googleapis/nodejs-projectify/compare/v1.0.3...v1.0.4) (2019-12-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **publish:** publication failed to reach npm ([#141](https://www.github.com/googleapis/nodejs-projectify/issues/141)) ([5406ba5](https://www.github.com/googleapis/nodejs-projectify/commit/5406ba5e1d43a228a19072023c1baebce34190af))
|
||||||
|
|
||||||
|
### [1.0.3](https://www.github.com/googleapis/nodejs-projectify/compare/v1.0.2...v1.0.3) (2019-12-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** pin TypeScript below 3.7.0 ([6c95307](https://www.github.com/googleapis/nodejs-projectify/commit/6c953070139a77d30c4ce5b7dee1443874046906))
|
||||||
|
|
||||||
|
### [1.0.2](https://www.github.com/googleapis/nodejs-projectify/compare/v1.0.1...v1.0.2) (2019-11-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** add jsdoc-region-tag plugin ([#135](https://www.github.com/googleapis/nodejs-projectify/issues/135)) ([59301e7](https://www.github.com/googleapis/nodejs-projectify/commit/59301e7cfa855add4894dd9c46870e61fffa7413))
|
||||||
|
|
||||||
|
### [1.0.1](https://www.github.com/googleapis/nodejs-projectify/compare/v1.0.0...v1.0.1) (2019-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** link to reference docs section on googleapis.dev ([#119](https://www.github.com/googleapis/nodejs-projectify/issues/119)) ([90a009f](https://www.github.com/googleapis/nodejs-projectify/commit/90a009f))
|
||||||
|
|
||||||
|
## [1.0.0](https://www.github.com/googleapis/nodejs-projectify/compare/v0.3.3...v1.0.0) (2019-05-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* upgrade engines field to >=8.10.0 ([#103](https://www.github.com/googleapis/nodejs-projectify/issues/103)) ([0149650](https://www.github.com/googleapis/nodejs-projectify/commit/0149650))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* upgrade engines field to >=8.10.0 (#103)
|
||||||
|
|
||||||
|
## v0.3.3
|
||||||
|
|
||||||
|
03-12-2019 12:27 PDT
|
||||||
|
|
||||||
|
This patch release contains a few updates to the docs. That's all!
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- docs: update links in contrib guide ([#86](https://github.com/googleapis/nodejs-projectify/pull/86))
|
||||||
|
- docs: update contributing path in README ([#82](https://github.com/googleapis/nodejs-projectify/pull/82))
|
||||||
|
- docs: move CONTRIBUTING.md to root ([#81](https://github.com/googleapis/nodejs-projectify/pull/81))
|
||||||
|
- docs: add lint/fix example to contributing guide ([#79](https://github.com/googleapis/nodejs-projectify/pull/79))
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- build: Add docuploader credentials to node publish jobs ([#90](https://github.com/googleapis/nodejs-projectify/pull/90))
|
||||||
|
- build: use node10 to run samples-test, system-test etc ([#89](https://github.com/googleapis/nodejs-projectify/pull/89))
|
||||||
|
- build: update release configuration
|
||||||
|
- chore(deps): update dependency mocha to v6
|
||||||
|
- build: use linkinator for docs test ([#85](https://github.com/googleapis/nodejs-projectify/pull/85))
|
||||||
|
- build: create docs test npm scripts ([#84](https://github.com/googleapis/nodejs-projectify/pull/84))
|
||||||
|
- build: test using @grpc/grpc-js in CI ([#83](https://github.com/googleapis/nodejs-projectify/pull/83))
|
||||||
|
- build: ignore googleapis.com in doc link check ([#78](https://github.com/googleapis/nodejs-projectify/pull/78))
|
||||||
|
- build: check for 404s in the docs ([#77](https://github.com/googleapis/nodejs-projectify/pull/77))
|
||||||
|
- chore(build): inject yoshi automation key ([#75](https://github.com/googleapis/nodejs-projectify/pull/75))
|
||||||
|
- chore: update nyc and eslint configs ([#74](https://github.com/googleapis/nodejs-projectify/pull/74))
|
||||||
|
- chore: fix publish.sh permission +x ([#72](https://github.com/googleapis/nodejs-projectify/pull/72))
|
||||||
|
- fix(build): fix Kokoro release script ([#71](https://github.com/googleapis/nodejs-projectify/pull/71))
|
||||||
|
- build: add Kokoro configs for autorelease ([#70](https://github.com/googleapis/nodejs-projectify/pull/70))
|
||||||
|
- chore: always nyc report before calling codecov ([#67](https://github.com/googleapis/nodejs-projectify/pull/67))
|
||||||
|
- chore: nyc ignore build/test by default ([#66](https://github.com/googleapis/nodejs-projectify/pull/66))
|
||||||
|
- chore(build): update prettier config ([#64](https://github.com/googleapis/nodejs-projectify/pull/64))
|
||||||
|
- chore: update license file ([#63](https://github.com/googleapis/nodejs-projectify/pull/63))
|
||||||
|
- fix(build): fix system key decryption ([#59](https://github.com/googleapis/nodejs-projectify/pull/59))
|
||||||
|
- chore: add synth.metadata
|
||||||
|
|
||||||
|
## v0.3.2
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
- fix: do not replace projectId on stream objects ([#53](https://github.com/googleapis/nodejs-projectify/pull/53))
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- chore(deps): update dependency gts to ^0.9.0 ([#52](https://github.com/googleapis/nodejs-projectify/pull/52))
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- chore: update eslintignore config ([#51](https://github.com/googleapis/nodejs-projectify/pull/51))
|
||||||
|
- chore: use latest npm on Windows ([#50](https://github.com/googleapis/nodejs-projectify/pull/50))
|
||||||
|
- chore: update CircleCI config ([#49](https://github.com/googleapis/nodejs-projectify/pull/49))
|
||||||
|
- chore: include build in eslintignore ([#46](https://github.com/googleapis/nodejs-projectify/pull/46))
|
||||||
|
|
||||||
|
## v0.3.1
|
||||||
|
|
||||||
|
### Implementation Changes
|
||||||
|
- fix: replaceProjectId should not fail when passed a Buffer ([#43](https://github.com/googleapis/nodejs-projectify/pull/43))
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- chore(deps): update dependency nyc to v13 ([#13](https://github.com/googleapis/nodejs-projectify/pull/13))
|
||||||
|
- chore(deps): lock file maintenance ([#11](https://github.com/googleapis/nodejs-projectify/pull/11))
|
||||||
|
- chore(deps): lock file maintenance ([#8](https://github.com/googleapis/nodejs-projectify/pull/8))
|
||||||
|
- chore(deps): update dependency typescript to v3 ([#7](https://github.com/googleapis/nodejs-projectify/pull/7))
|
||||||
|
- chore(deps): update dependency gts to ^0.8.0 ([#2](https://github.com/googleapis/nodejs-projectify/pull/2))
|
||||||
|
- chore(deps): lock file maintenance ([#4](https://github.com/googleapis/nodejs-projectify/pull/4))
|
||||||
|
- chore(deps): lock file maintenance ([#3](https://github.com/googleapis/nodejs-projectify/pull/3))
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- chore: update issue templates ([#40](https://github.com/googleapis/nodejs-projectify/pull/40))
|
||||||
|
- chore: remove old issue template ([#38](https://github.com/googleapis/nodejs-projectify/pull/38))
|
||||||
|
- build: run tests on node11 ([#37](https://github.com/googleapis/nodejs-projectify/pull/37))
|
||||||
|
- chores(build): run codecov on continuous builds ([#34](https://github.com/googleapis/nodejs-projectify/pull/34))
|
||||||
|
- chores(build): do not collect sponge.xml from windows builds ([#35](https://github.com/googleapis/nodejs-projectify/pull/35))
|
||||||
|
- chore: update new issue template ([#33](https://github.com/googleapis/nodejs-projectify/pull/33))
|
||||||
|
- build: fix codecov uploading on Kokoro ([#30](https://github.com/googleapis/nodejs-projectify/pull/30))
|
||||||
|
- Update kokoro config ([#28](https://github.com/googleapis/nodejs-projectify/pull/28))
|
||||||
|
- Update CI config ([#26](https://github.com/googleapis/nodejs-projectify/pull/26))
|
||||||
|
- Don't publish sourcemaps ([#24](https://github.com/googleapis/nodejs-projectify/pull/24))
|
||||||
|
- build: prevent system/sample-test from leaking credentials
|
||||||
|
- Update kokoro config ([#22](https://github.com/googleapis/nodejs-projectify/pull/22))
|
||||||
|
- test: remove appveyor config ([#21](https://github.com/googleapis/nodejs-projectify/pull/21))
|
||||||
|
- Update CI config ([#20](https://github.com/googleapis/nodejs-projectify/pull/20))
|
||||||
|
- Enable prefer-const in the eslint config ([#19](https://github.com/googleapis/nodejs-projectify/pull/19))
|
||||||
|
- Enable no-var in eslint ([#18](https://github.com/googleapis/nodejs-projectify/pull/18))
|
||||||
|
- Update CI config ([#17](https://github.com/googleapis/nodejs-projectify/pull/17))
|
||||||
|
- Add synth and update CI config ([#15](https://github.com/googleapis/nodejs-projectify/pull/15))
|
||||||
|
- chore: ignore package-lock.json ([#12](https://github.com/googleapis/nodejs-projectify/pull/12))
|
||||||
|
- chore: update renovate config ([#10](https://github.com/googleapis/nodejs-projectify/pull/10))
|
||||||
|
- remove that whitespace ([#9](https://github.com/googleapis/nodejs-projectify/pull/9))
|
||||||
|
- chore: assert.deelEqual => assert.deepStrictEqual ([#6](https://github.com/googleapis/nodejs-projectify/pull/6))
|
||||||
|
- chore: move mocha options to mocha.opts ([#5](https://github.com/googleapis/nodejs-projectify/pull/5))
|
202
em2rp/node_modules/@google-cloud/projectify/LICENSE
generated
vendored
Normal file
202
em2rp/node_modules/@google-cloud/projectify/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
138
em2rp/node_modules/@google-cloud/projectify/README.md
generated
vendored
Normal file
138
em2rp/node_modules/@google-cloud/projectify/README.md
generated
vendored
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
[//]: # "This README.md file is auto-generated, all changes to this file will be lost."
|
||||||
|
[//]: # "To regenerate it, use `python -m synthtool`."
|
||||||
|
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
|
||||||
|
|
||||||
|
# [Google Cloud Common Projectify: Node.js Client](https://github.com/googleapis/nodejs-projectify)
|
||||||
|
|
||||||
|
[](https://cloud.google.com/terms/launch-stages)
|
||||||
|
[](https://www.npmjs.org/package/@google-cloud/projectify)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A simple utility for replacing the projectid token in objects.
|
||||||
|
|
||||||
|
|
||||||
|
A comprehensive list of changes in each version may be found in
|
||||||
|
[the CHANGELOG](https://github.com/googleapis/nodejs-projectify/blob/main/CHANGELOG.md).
|
||||||
|
|
||||||
|
* [Google Cloud Common Projectify Node.js Client API Reference][client-docs]
|
||||||
|
|
||||||
|
* [github.com/googleapis/nodejs-projectify](https://github.com/googleapis/nodejs-projectify)
|
||||||
|
|
||||||
|
Read more about the client libraries for Cloud APIs, including the older
|
||||||
|
Google APIs Client Libraries, in [Client Libraries Explained][explained].
|
||||||
|
|
||||||
|
[explained]: https://cloud.google.com/apis/docs/client-libraries-explained
|
||||||
|
|
||||||
|
**Table of contents:**
|
||||||
|
|
||||||
|
|
||||||
|
* [Quickstart](#quickstart)
|
||||||
|
|
||||||
|
* [Installing the client library](#installing-the-client-library)
|
||||||
|
* [Using the client library](#using-the-client-library)
|
||||||
|
* [Samples](#samples)
|
||||||
|
* [Versioning](#versioning)
|
||||||
|
* [Contributing](#contributing)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
### Installing the client library
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @google-cloud/projectify
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Using the client library
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const {replaceProjectIdToken} = require('@google-cloud/projectify');
|
||||||
|
const options = {
|
||||||
|
projectId: '{{projectId}}',
|
||||||
|
};
|
||||||
|
replaceProjectIdToken(options, 'fake-project-id');
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Samples
|
||||||
|
|
||||||
|
Samples are in the [`samples/`](https://github.com/googleapis/nodejs-projectify/tree/main/samples) directory. Each sample's `README.md` has instructions for running its sample.
|
||||||
|
|
||||||
|
| Sample | Source Code | Try it |
|
||||||
|
| --------------------------- | --------------------------------- | ------ |
|
||||||
|
| Quickstart | [source code](https://github.com/googleapis/nodejs-projectify/blob/main/samples/quickstart.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-projectify&page=editor&open_in_editor=samples/quickstart.js,samples/README.md) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The [Google Cloud Common Projectify Node.js Client API Reference][client-docs] documentation
|
||||||
|
also contains samples.
|
||||||
|
|
||||||
|
## Supported Node.js Versions
|
||||||
|
|
||||||
|
Our client libraries follow the [Node.js release schedule](https://github.com/nodejs/release#release-schedule).
|
||||||
|
Libraries are compatible with all current _active_ and _maintenance_ versions of
|
||||||
|
Node.js.
|
||||||
|
If you are using an end-of-life version of Node.js, we recommend that you update
|
||||||
|
as soon as possible to an actively supported LTS version.
|
||||||
|
|
||||||
|
Google's client libraries support legacy versions of Node.js runtimes on a
|
||||||
|
best-efforts basis with the following warnings:
|
||||||
|
|
||||||
|
* Legacy versions are not tested in continuous integration.
|
||||||
|
* Some security patches and features cannot be backported.
|
||||||
|
* Dependencies cannot be kept up-to-date.
|
||||||
|
|
||||||
|
Client libraries targeting some end-of-life versions of Node.js are available, and
|
||||||
|
can be installed through npm [dist-tags](https://docs.npmjs.com/cli/dist-tag).
|
||||||
|
The dist-tags follow the naming convention `legacy-(version)`.
|
||||||
|
For example, `npm install @google-cloud/projectify@legacy-8` installs client libraries
|
||||||
|
for versions compatible with Node.js 8.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
This library follows [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This library is considered to be **stable**. The code surface will not change in backwards-incompatible ways
|
||||||
|
unless absolutely necessary (e.g. because of critical security issues) or with
|
||||||
|
an extensive deprecation period. Issues and requests against **stable** libraries
|
||||||
|
are addressed with the highest priority.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
More Information: [Google Cloud Platform Launch Stages][launch_stages]
|
||||||
|
|
||||||
|
[launch_stages]: https://cloud.google.com/terms/launch-stages
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions welcome! See the [Contributing Guide](https://github.com/googleapis/nodejs-projectify/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
Please note that this `README.md`, the `samples/README.md`,
|
||||||
|
and a variety of configuration files in this repository (including `.nycrc` and `tsconfig.json`)
|
||||||
|
are generated from a central template. To edit one of these files, make an edit
|
||||||
|
to its templates in
|
||||||
|
[directory](https://github.com/googleapis/synthtool).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache Version 2.0
|
||||||
|
|
||||||
|
See [LICENSE](https://github.com/googleapis/nodejs-projectify/blob/main/LICENSE)
|
||||||
|
|
||||||
|
[client-docs]: https://cloud.google.com/nodejs/docs/reference/projectify/latest
|
||||||
|
|
||||||
|
[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
|
||||||
|
[projects]: https://console.cloud.google.com/project
|
||||||
|
[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
|
||||||
|
|
||||||
|
[auth]: https://cloud.google.com/docs/authentication/getting-started
|
46
em2rp/node_modules/@google-cloud/projectify/package.json
generated
vendored
Normal file
46
em2rp/node_modules/@google-cloud/projectify/package.json
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "@google-cloud/projectify",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"description": "A simple utility for replacing the projectid token in objects.",
|
||||||
|
"main": "build/src/index.js",
|
||||||
|
"types": "build/src/index.d.ts",
|
||||||
|
"repository": "googleapis/nodejs-projectify",
|
||||||
|
"scripts": {
|
||||||
|
"test": "c8 mocha build/test",
|
||||||
|
"lint": "gts check",
|
||||||
|
"clean": "gts clean",
|
||||||
|
"compile": "tsc -p .",
|
||||||
|
"fix": "gts fix",
|
||||||
|
"prepare": "npm run compile",
|
||||||
|
"pretest": "npm run compile",
|
||||||
|
"docs": "compodoc src/",
|
||||||
|
"presystem-test": "npm run compile",
|
||||||
|
"samples-test": "cd samples/ && npm link ../ && npm test && cd ../",
|
||||||
|
"system-test": "mocha build/system-test",
|
||||||
|
"docs-test": "linkinator docs",
|
||||||
|
"predocs-test": "npm run docs",
|
||||||
|
"prelint": "cd samples; npm link ../; npm install",
|
||||||
|
"precompile": "gts clean"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"files": [
|
||||||
|
"build/src",
|
||||||
|
"!build/src/**/*.map"
|
||||||
|
],
|
||||||
|
"author": "Google Inc.",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@compodoc/compodoc": "^1.1.11",
|
||||||
|
"@types/mocha": "^9.0.0",
|
||||||
|
"@types/node": "^20.4.9",
|
||||||
|
"c8": "^8.0.1",
|
||||||
|
"codecov": "^3.6.5",
|
||||||
|
"gts": "^5.0.0",
|
||||||
|
"linkinator": "^4.0.0",
|
||||||
|
"mocha": "^9.2.2",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
}
|
191
em2rp/node_modules/@google-cloud/promisify/CHANGELOG.md
generated
vendored
Normal file
191
em2rp/node_modules/@google-cloud/promisify/CHANGELOG.md
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
[npm history][1]
|
||||||
|
|
||||||
|
[1]: https://www.npmjs.com/package/nodejs-promisify?activeTab=versions
|
||||||
|
|
||||||
|
## [4.0.0](https://github.com/googleapis/nodejs-promisify/compare/v3.0.1...v4.0.0) (2023-08-08)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* upgrade to Node 14 ([#325](https://github.com/googleapis/nodejs-promisify/issues/325))
|
||||||
|
|
||||||
|
### Miscellaneous Chores
|
||||||
|
|
||||||
|
* Upgrade to Node 14 ([#325](https://github.com/googleapis/nodejs-promisify/issues/325)) ([57d02c1](https://github.com/googleapis/nodejs-promisify/commit/57d02c1c23c65d63131bb99c07919ff80e5604cd))
|
||||||
|
|
||||||
|
## [3.0.1](https://github.com/googleapis/nodejs-promisify/compare/v3.0.0...v3.0.1) (2022-08-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove pip install statements ([#1546](https://github.com/googleapis/nodejs-promisify/issues/1546)) ([#310](https://github.com/googleapis/nodejs-promisify/issues/310)) ([c7c6883](https://github.com/googleapis/nodejs-promisify/commit/c7c688389de72ddc0181b19bceee2d95eacd3d96))
|
||||||
|
|
||||||
|
## [3.0.0](https://github.com/googleapis/nodejs-promisify/compare/v2.0.4...v3.0.0) (2022-05-03)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* drop node 10 from engines list, update typescript to 4.6.3 (#300)
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* drop node 10 from engines list, update typescript to 4.6.3 ([#300](https://github.com/googleapis/nodejs-promisify/issues/300)) ([fed2f14](https://github.com/googleapis/nodejs-promisify/commit/fed2f145a5256c939eb66b85a5c7c48332b8841d))
|
||||||
|
|
||||||
|
### [2.0.4](https://www.github.com/googleapis/nodejs-promisify/compare/v2.0.3...v2.0.4) (2021-09-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **build:** switch primary branch to main ([#270](https://www.github.com/googleapis/nodejs-promisify/issues/270)) ([11242f7](https://www.github.com/googleapis/nodejs-promisify/commit/11242f7f76e170dae7a429f8d4064bf33be9bb3f))
|
||||||
|
|
||||||
|
### [2.0.3](https://www.github.com/googleapis/nodejs-promisify/compare/v2.0.2...v2.0.3) (2020-09-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* allow excluding accessor methods ([#228](https://www.github.com/googleapis/nodejs-promisify/issues/228)) ([114d8bc](https://www.github.com/googleapis/nodejs-promisify/commit/114d8bcef7093bdfda195a15e0c2f376195fd3fc))
|
||||||
|
|
||||||
|
### [2.0.2](https://www.github.com/googleapis/nodejs-promisify/compare/v2.0.1...v2.0.2) (2020-07-06)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* update node issue template ([#204](https://www.github.com/googleapis/nodejs-promisify/issues/204)) ([a2ba8d8](https://www.github.com/googleapis/nodejs-promisify/commit/a2ba8d8e45ef03d093d987292a467696745fc9fd))
|
||||||
|
|
||||||
|
### [2.0.1](https://www.github.com/googleapis/nodejs-promisify/compare/v2.0.0...v2.0.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* apache license URL ([#468](https://www.github.com/googleapis/nodejs-promisify/issues/468)) ([#191](https://www.github.com/googleapis/nodejs-promisify/issues/191)) ([0edc724](https://www.github.com/googleapis/nodejs-promisify/commit/0edc7246c53d25d9dd220b813561bcee97250783))
|
||||||
|
|
||||||
|
## [2.0.0](https://www.github.com/googleapis/nodejs-promisify/compare/v1.0.4...v2.0.0) (2020-03-23)
|
||||||
|
|
||||||
|
|
||||||
|
### ⚠ BREAKING CHANGES
|
||||||
|
|
||||||
|
* update to latest version of gts/typescript (#183)
|
||||||
|
* drop Node 8 from engines field (#184)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* drop Node 8 from engines field ([#184](https://www.github.com/googleapis/nodejs-promisify/issues/184)) ([7e6d3c5](https://www.github.com/googleapis/nodejs-promisify/commit/7e6d3c54066d89530ed25c7f9722efd252f43fb8))
|
||||||
|
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* update to latest version of gts/typescript ([#183](https://www.github.com/googleapis/nodejs-promisify/issues/183)) ([9c3ed12](https://www.github.com/googleapis/nodejs-promisify/commit/9c3ed12c12f4bb1e17af7440c6371c4cefddcd59))
|
||||||
|
|
||||||
|
### [1.0.4](https://www.github.com/googleapis/nodejs-promisify/compare/v1.0.3...v1.0.4) (2019-12-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** pin TypeScript below 3.7.0 ([e48750e](https://www.github.com/googleapis/nodejs-promisify/commit/e48750ef96aa20eb3a2b73fe2f062d04430468a7))
|
||||||
|
|
||||||
|
### [1.0.3](https://www.github.com/googleapis/nodejs-promisify/compare/v1.0.2...v1.0.3) (2019-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** add jsdoc-region-tag plugin ([#146](https://www.github.com/googleapis/nodejs-promisify/issues/146)) ([ff0ee74](https://www.github.com/googleapis/nodejs-promisify/commit/ff0ee7408f50e8f7147b8ccf7e10337aa5920076))
|
||||||
|
|
||||||
|
### [1.0.2](https://www.github.com/googleapis/nodejs-promisify/compare/v1.0.1...v1.0.2) (2019-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** link to reference docs section on googleapis.dev ([#128](https://www.github.com/googleapis/nodejs-promisify/issues/128)) ([5a8bd90](https://www.github.com/googleapis/nodejs-promisify/commit/5a8bd90))
|
||||||
|
|
||||||
|
### [1.0.1](https://www.github.com/googleapis/nodejs-promisify/compare/v1.0.0...v1.0.1) (2019-06-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **docs:** move to new client docs URL ([#124](https://www.github.com/googleapis/nodejs-promisify/issues/124)) ([34d18cd](https://www.github.com/googleapis/nodejs-promisify/commit/34d18cd))
|
||||||
|
|
||||||
|
## [1.0.0](https://www.github.com/googleapis/nodejs-promisify/compare/v0.4.0...v1.0.0) (2019-05-02)
|
||||||
|
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
* upgrade engines field to >=8.10.0 ([#108](https://www.github.com/googleapis/nodejs-promisify/issues/108)) ([78ab89c](https://www.github.com/googleapis/nodejs-promisify/commit/78ab89c))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* upgrade engines field to >=8.10.0 (#108)
|
||||||
|
|
||||||
|
## v0.4.0
|
||||||
|
|
||||||
|
02-12-2019 19:44 PST
|
||||||
|
|
||||||
|
### New features
|
||||||
|
- feat: add callbackify() and callbackifyAll() methods ([#82](https://github.com/googleapis/nodejs-promisify/pull/82))
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
- docs: update contributing path in README ([#86](https://github.com/googleapis/nodejs-promisify/pull/86))
|
||||||
|
- chore: move CONTRIBUTING.md to root ([#85](https://github.com/googleapis/nodejs-promisify/pull/85))
|
||||||
|
- docs: add lint/fix example to contributing guide ([#83](https://github.com/googleapis/nodejs-promisify/pull/83))
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- build: create docs test npm scripts ([#88](https://github.com/googleapis/nodejs-promisify/pull/88))
|
||||||
|
- build: test using @grpc/grpc-js in CI ([#87](https://github.com/googleapis/nodejs-promisify/pull/87))
|
||||||
|
- build: ignore googleapis.com in doc link check ([#81](https://github.com/googleapis/nodejs-promisify/pull/81))
|
||||||
|
- build: check broken links in generated docs ([#79](https://github.com/googleapis/nodejs-promisify/pull/79))
|
||||||
|
- chore(deps): update dependency @types/sinon to v7 ([#78](https://github.com/googleapis/nodejs-promisify/pull/78))
|
||||||
|
- chore(build): inject yoshi automation key ([#77](https://github.com/googleapis/nodejs-promisify/pull/77))
|
||||||
|
- chore: update nyc and eslint configs ([#76](https://github.com/googleapis/nodejs-promisify/pull/76))
|
||||||
|
- chore: fix publish.sh permission +x ([#74](https://github.com/googleapis/nodejs-promisify/pull/74))
|
||||||
|
- fix(build): fix Kokoro release script ([#73](https://github.com/googleapis/nodejs-promisify/pull/73))
|
||||||
|
- build: add Kokoro configs for autorelease ([#72](https://github.com/googleapis/nodejs-promisify/pull/72))
|
||||||
|
- chore: always nyc report before calling codecov ([#69](https://github.com/googleapis/nodejs-promisify/pull/69))
|
||||||
|
- chore: nyc ignore build/test by default ([#68](https://github.com/googleapis/nodejs-promisify/pull/68))
|
||||||
|
- chore(build): update prettier config ([#66](https://github.com/googleapis/nodejs-promisify/pull/66))
|
||||||
|
- fix: get the build passing ([#65](https://github.com/googleapis/nodejs-promisify/pull/65))
|
||||||
|
- chore: update license file ([#64](https://github.com/googleapis/nodejs-promisify/pull/64))
|
||||||
|
- fix(build): fix system key decryption ([#60](https://github.com/googleapis/nodejs-promisify/pull/60))
|
||||||
|
- chore(deps): update dependency @types/sinon to v5.0.7 ([#58](https://github.com/googleapis/nodejs-promisify/pull/58))
|
||||||
|
- fix: Pin @types/sinon to last compatible version ([#57](https://github.com/googleapis/nodejs-promisify/pull/57))
|
||||||
|
- chore: add synth.metadata
|
||||||
|
- chore(deps): update dependency gts to ^0.9.0 ([#54](https://github.com/googleapis/nodejs-promisify/pull/54))
|
||||||
|
- chore: update eslintignore config ([#53](https://github.com/googleapis/nodejs-promisify/pull/53))
|
||||||
|
- chore: use latest npm on Windows ([#52](https://github.com/googleapis/nodejs-promisify/pull/52))
|
||||||
|
- chore: update CircleCI config ([#51](https://github.com/googleapis/nodejs-promisify/pull/51))
|
||||||
|
- chore: include build in eslintignore ([#48](https://github.com/googleapis/nodejs-promisify/pull/48))
|
||||||
|
- chore: update issue templates ([#44](https://github.com/googleapis/nodejs-promisify/pull/44))
|
||||||
|
- chore: remove old issue template ([#42](https://github.com/googleapis/nodejs-promisify/pull/42))
|
||||||
|
- build: run tests on node11 ([#41](https://github.com/googleapis/nodejs-promisify/pull/41))
|
||||||
|
- chores(build): do not collect sponge.xml from windows builds ([#40](https://github.com/googleapis/nodejs-promisify/pull/40))
|
||||||
|
- chores(build): run codecov on continuous builds ([#39](https://github.com/googleapis/nodejs-promisify/pull/39))
|
||||||
|
- chore: update new issue template ([#38](https://github.com/googleapis/nodejs-promisify/pull/38))
|
||||||
|
- chore(deps): update dependency sinon to v7 ([#33](https://github.com/googleapis/nodejs-promisify/pull/33))
|
||||||
|
- build: fix codecov uploading on Kokoro ([#34](https://github.com/googleapis/nodejs-promisify/pull/34))
|
||||||
|
- Update kokoro config ([#30](https://github.com/googleapis/nodejs-promisify/pull/30))
|
||||||
|
- Update CI config ([#28](https://github.com/googleapis/nodejs-promisify/pull/28))
|
||||||
|
- Don't publish sourcemaps ([#26](https://github.com/googleapis/nodejs-promisify/pull/26))
|
||||||
|
- Update kokoro config ([#24](https://github.com/googleapis/nodejs-promisify/pull/24))
|
||||||
|
- test: remove appveyor config ([#23](https://github.com/googleapis/nodejs-promisify/pull/23))
|
||||||
|
- Update CI config ([#22](https://github.com/googleapis/nodejs-promisify/pull/22))
|
||||||
|
- Enable prefer-const in the eslint config ([#21](https://github.com/googleapis/nodejs-promisify/pull/21))
|
||||||
|
- Enable no-var in eslint ([#19](https://github.com/googleapis/nodejs-promisify/pull/19))
|
||||||
|
- Update CI config ([#18](https://github.com/googleapis/nodejs-promisify/pull/18))
|
||||||
|
|
||||||
|
## v0.3.1
|
||||||
|
|
||||||
|
### Internal / Testing Changes
|
||||||
|
- Add synth script and update CI (#14)
|
||||||
|
- chore(deps): update dependency nyc to v13 (#12)
|
||||||
|
- chore: ignore package-lock.json (#11)
|
||||||
|
- chore(deps): lock file maintenance (#10)
|
||||||
|
- chore: update renovate config (#9)
|
||||||
|
- remove that whitespace (#8)
|
||||||
|
- chore(deps): lock file maintenance (#7)
|
||||||
|
- chore(deps): update dependency typescript to v3 (#6)
|
||||||
|
- chore: assert.deelEqual => assert.deepStrictEqual (#5)
|
||||||
|
- chore: move mocha options to mocha.opts (#4)
|
||||||
|
- chore(deps): update dependency gts to ^0.8.0 (#1)
|
||||||
|
- chore(deps): lock file maintenance (#3)
|
||||||
|
- chore(deps): lock file maintenance (#2)
|
202
em2rp/node_modules/@google-cloud/promisify/LICENSE
generated
vendored
Normal file
202
em2rp/node_modules/@google-cloud/promisify/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
156
em2rp/node_modules/@google-cloud/promisify/README.md
generated
vendored
Normal file
156
em2rp/node_modules/@google-cloud/promisify/README.md
generated
vendored
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
[//]: # "This README.md file is auto-generated, all changes to this file will be lost."
|
||||||
|
[//]: # "To regenerate it, use `python -m synthtool`."
|
||||||
|
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
|
||||||
|
|
||||||
|
# [Google Cloud Common Promisify: Node.js Client](https://github.com/googleapis/nodejs-promisify)
|
||||||
|
|
||||||
|
[](https://cloud.google.com/terms/launch-stages)
|
||||||
|
[](https://www.npmjs.org/package/@google-cloud/promisify)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A simple utility for promisifying functions and classes.
|
||||||
|
|
||||||
|
|
||||||
|
A comprehensive list of changes in each version may be found in
|
||||||
|
[the CHANGELOG](https://github.com/googleapis/nodejs-promisify/blob/main/CHANGELOG.md).
|
||||||
|
|
||||||
|
* [Google Cloud Common Promisify Node.js Client API Reference][client-docs]
|
||||||
|
|
||||||
|
* [github.com/googleapis/nodejs-promisify](https://github.com/googleapis/nodejs-promisify)
|
||||||
|
|
||||||
|
Read more about the client libraries for Cloud APIs, including the older
|
||||||
|
Google APIs Client Libraries, in [Client Libraries Explained][explained].
|
||||||
|
|
||||||
|
[explained]: https://cloud.google.com/apis/docs/client-libraries-explained
|
||||||
|
|
||||||
|
**Table of contents:**
|
||||||
|
|
||||||
|
|
||||||
|
* [Quickstart](#quickstart)
|
||||||
|
|
||||||
|
* [Installing the client library](#installing-the-client-library)
|
||||||
|
* [Using the client library](#using-the-client-library)
|
||||||
|
* [Samples](#samples)
|
||||||
|
* [Versioning](#versioning)
|
||||||
|
* [Contributing](#contributing)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
### Installing the client library
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @google-cloud/promisify
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Using the client library
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const {promisify} = require('@google-cloud/promisify');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a very basic example function that accepts a callback.
|
||||||
|
*/
|
||||||
|
function someCallbackFunction(name, callback) {
|
||||||
|
if (!name) {
|
||||||
|
callback(new Error('Name is required!'));
|
||||||
|
} else {
|
||||||
|
callback(null, `Well hello there, ${name}!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's promisify it!
|
||||||
|
const somePromiseFunction = promisify(someCallbackFunction);
|
||||||
|
|
||||||
|
async function quickstart() {
|
||||||
|
// now we can just `await` the function to use it like a promisified method
|
||||||
|
const [result] = await somePromiseFunction('nodestronaut');
|
||||||
|
console.log(result);
|
||||||
|
}
|
||||||
|
quickstart();
|
||||||
|
|
||||||
|
```
|
||||||
|
It's unlikely you will need to install this package directly, as it will be
|
||||||
|
installed as a dependency when you install other `@google-cloud` packages.
|
||||||
|
|
||||||
|
|
||||||
|
## Samples
|
||||||
|
|
||||||
|
Samples are in the [`samples/`](https://github.com/googleapis/nodejs-promisify/tree/main/samples) directory. Each sample's `README.md` has instructions for running its sample.
|
||||||
|
|
||||||
|
| Sample | Source Code | Try it |
|
||||||
|
| --------------------------- | --------------------------------- | ------ |
|
||||||
|
| Quickstart | [source code](https://github.com/googleapis/nodejs-promisify/blob/main/samples/quickstart.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-promisify&page=editor&open_in_editor=samples/quickstart.js,samples/README.md) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The [Google Cloud Common Promisify Node.js Client API Reference][client-docs] documentation
|
||||||
|
also contains samples.
|
||||||
|
|
||||||
|
## Supported Node.js Versions
|
||||||
|
|
||||||
|
Our client libraries follow the [Node.js release schedule](https://github.com/nodejs/release#release-schedule).
|
||||||
|
Libraries are compatible with all current _active_ and _maintenance_ versions of
|
||||||
|
Node.js.
|
||||||
|
If you are using an end-of-life version of Node.js, we recommend that you update
|
||||||
|
as soon as possible to an actively supported LTS version.
|
||||||
|
|
||||||
|
Google's client libraries support legacy versions of Node.js runtimes on a
|
||||||
|
best-efforts basis with the following warnings:
|
||||||
|
|
||||||
|
* Legacy versions are not tested in continuous integration.
|
||||||
|
* Some security patches and features cannot be backported.
|
||||||
|
* Dependencies cannot be kept up-to-date.
|
||||||
|
|
||||||
|
Client libraries targeting some end-of-life versions of Node.js are available, and
|
||||||
|
can be installed through npm [dist-tags](https://docs.npmjs.com/cli/dist-tag).
|
||||||
|
The dist-tags follow the naming convention `legacy-(version)`.
|
||||||
|
For example, `npm install @google-cloud/promisify@legacy-8` installs client libraries
|
||||||
|
for versions compatible with Node.js 8.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
This library follows [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This library is considered to be **stable**. The code surface will not change in backwards-incompatible ways
|
||||||
|
unless absolutely necessary (e.g. because of critical security issues) or with
|
||||||
|
an extensive deprecation period. Issues and requests against **stable** libraries
|
||||||
|
are addressed with the highest priority.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
More Information: [Google Cloud Platform Launch Stages][launch_stages]
|
||||||
|
|
||||||
|
[launch_stages]: https://cloud.google.com/terms/launch-stages
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions welcome! See the [Contributing Guide](https://github.com/googleapis/nodejs-promisify/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
Please note that this `README.md`, the `samples/README.md`,
|
||||||
|
and a variety of configuration files in this repository (including `.nycrc` and `tsconfig.json`)
|
||||||
|
are generated from a central template. To edit one of these files, make an edit
|
||||||
|
to its templates in
|
||||||
|
[directory](https://github.com/googleapis/synthtool).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache Version 2.0
|
||||||
|
|
||||||
|
See [LICENSE](https://github.com/googleapis/nodejs-promisify/blob/main/LICENSE)
|
||||||
|
|
||||||
|
[client-docs]: https://googleapis.dev/nodejs/promisify/latest
|
||||||
|
|
||||||
|
[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
|
||||||
|
[projects]: https://console.cloud.google.com/project
|
||||||
|
[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
|
||||||
|
|
||||||
|
[auth]: https://cloud.google.com/docs/authentication/getting-started
|
50
em2rp/node_modules/@google-cloud/promisify/package.json
generated
vendored
Normal file
50
em2rp/node_modules/@google-cloud/promisify/package.json
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"name": "@google-cloud/promisify",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"description": "A simple utility for promisifying functions and classes.",
|
||||||
|
"main": "build/src/index.js",
|
||||||
|
"types": "build/src/index.d.ts",
|
||||||
|
"repository": "googleapis/nodejs-promisify",
|
||||||
|
"scripts": {
|
||||||
|
"test": "c8 mocha build/test",
|
||||||
|
"lint": "gts check",
|
||||||
|
"compile": "tsc -p .",
|
||||||
|
"fix": "gts fix",
|
||||||
|
"prepare": "npm run compile",
|
||||||
|
"pretest": "npm run compile",
|
||||||
|
"docs": "compodoc src/",
|
||||||
|
"presystem-test": "npm run compile",
|
||||||
|
"samples-test": "cd samples/ && npm link ../ && npm test && cd ../",
|
||||||
|
"system-test": "mocha build/system-test",
|
||||||
|
"docs-test": "linkinator docs",
|
||||||
|
"predocs-test": "npm run docs",
|
||||||
|
"prelint": "cd samples; npm link ../; npm install",
|
||||||
|
"clean": "gts clean",
|
||||||
|
"precompile": "gts clean"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"files": [
|
||||||
|
"build/src",
|
||||||
|
"!build/src/**/*.map"
|
||||||
|
],
|
||||||
|
"author": "Google Inc.",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"devDependencies": {
|
||||||
|
"@compodoc/compodoc": "^1.1.9",
|
||||||
|
"@types/mocha": "^9.0.0",
|
||||||
|
"@types/node": "^20.4.8",
|
||||||
|
"@types/sinon": "^10.0.0",
|
||||||
|
"c8": "^8.0.1",
|
||||||
|
"chai": "^4.2.0",
|
||||||
|
"codecov": "^3.0.4",
|
||||||
|
"gts": "^5.0.0",
|
||||||
|
"hard-rejection": "^2.1.0",
|
||||||
|
"linkinator": "^5.0.1",
|
||||||
|
"mocha": "^8.0.0",
|
||||||
|
"sinon": "^15.0.0",
|
||||||
|
"typescript": "^5.1.6"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
}
|
||||||
|
}
|
1769
em2rp/node_modules/@google-cloud/storage/CHANGELOG.md
generated
vendored
Normal file
1769
em2rp/node_modules/@google-cloud/storage/CHANGELOG.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
202
em2rp/node_modules/@google-cloud/storage/LICENSE
generated
vendored
Normal file
202
em2rp/node_modules/@google-cloud/storage/LICENSE
generated
vendored
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
295
em2rp/node_modules/@google-cloud/storage/README.md
generated
vendored
Normal file
295
em2rp/node_modules/@google-cloud/storage/README.md
generated
vendored
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
[//]: # "This README.md file is auto-generated, all changes to this file will be lost."
|
||||||
|
[//]: # "To regenerate it, use `python -m synthtool`."
|
||||||
|
<img src="https://avatars2.githubusercontent.com/u/2810941?v=3&s=96" alt="Google Cloud Platform logo" title="Google Cloud Platform" align="right" height="96" width="96"/>
|
||||||
|
|
||||||
|
# [Google Cloud Storage: Node.js Client](https://github.com/googleapis/nodejs-storage)
|
||||||
|
|
||||||
|
[](https://cloud.google.com/terms/launch-stages)
|
||||||
|
[](https://www.npmjs.org/package/@google-cloud/storage)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> Node.js idiomatic client for [Cloud Storage][product-docs].
|
||||||
|
|
||||||
|
[Cloud Storage](https://cloud.google.com/storage/docs) allows world-wide
|
||||||
|
storage and retrieval of any amount of data at any time. You can use Google
|
||||||
|
Cloud Storage for a range of scenarios including serving website content,
|
||||||
|
storing data for archival and disaster recovery, or distributing large data
|
||||||
|
objects to users via direct download.
|
||||||
|
|
||||||
|
|
||||||
|
A comprehensive list of changes in each version may be found in
|
||||||
|
[the CHANGELOG](https://github.com/googleapis/nodejs-storage/blob/main/CHANGELOG.md).
|
||||||
|
|
||||||
|
* [Google Cloud Storage Node.js Client API Reference][client-docs]
|
||||||
|
* [Google Cloud Storage Documentation][product-docs]
|
||||||
|
* [github.com/googleapis/nodejs-storage](https://github.com/googleapis/nodejs-storage)
|
||||||
|
|
||||||
|
Read more about the client libraries for Cloud APIs, including the older
|
||||||
|
Google APIs Client Libraries, in [Client Libraries Explained][explained].
|
||||||
|
|
||||||
|
[explained]: https://cloud.google.com/apis/docs/client-libraries-explained
|
||||||
|
|
||||||
|
**Table of contents:**
|
||||||
|
|
||||||
|
|
||||||
|
* [Quickstart](#quickstart)
|
||||||
|
* [Before you begin](#before-you-begin)
|
||||||
|
* [Installing the client library](#installing-the-client-library)
|
||||||
|
* [Using the client library](#using-the-client-library)
|
||||||
|
* [Samples](#samples)
|
||||||
|
* [Versioning](#versioning)
|
||||||
|
* [Contributing](#contributing)
|
||||||
|
* [License](#license)
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
### Before you begin
|
||||||
|
|
||||||
|
1. [Select or create a Cloud Platform project][projects].
|
||||||
|
1. [Enable billing for your project][billing].
|
||||||
|
1. [Enable the Google Cloud Storage API][enable_api].
|
||||||
|
1. [Set up authentication][auth] so you can access the
|
||||||
|
API from your local workstation.
|
||||||
|
|
||||||
|
### Installing the client library
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @google-cloud/storage
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Using the client library
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Imports the Google Cloud client library
|
||||||
|
const {Storage} = require('@google-cloud/storage');
|
||||||
|
|
||||||
|
// For more information on ways to initialize Storage, please see
|
||||||
|
// https://googleapis.dev/nodejs/storage/latest/Storage.html
|
||||||
|
|
||||||
|
// Creates a client using Application Default Credentials
|
||||||
|
const storage = new Storage();
|
||||||
|
|
||||||
|
// Creates a client from a Google service account key
|
||||||
|
// const storage = new Storage({keyFilename: 'key.json'});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO(developer): Uncomment these variables before running the sample.
|
||||||
|
*/
|
||||||
|
// The ID of your GCS bucket
|
||||||
|
// const bucketName = 'your-unique-bucket-name';
|
||||||
|
|
||||||
|
async function createBucket() {
|
||||||
|
// Creates the new bucket
|
||||||
|
await storage.createBucket(bucketName);
|
||||||
|
console.log(`Bucket ${bucketName} created.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
createBucket().catch(console.error);
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Samples
|
||||||
|
|
||||||
|
Samples are in the [`samples/`](https://github.com/googleapis/nodejs-storage/tree/main/samples) directory. Each sample's `README.md` has instructions for running its sample.
|
||||||
|
|
||||||
|
| Sample | Source Code | Try it |
|
||||||
|
| --------------------------- | --------------------------------- | ------ |
|
||||||
|
| Add Bucket Conditional Binding | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addBucketConditionalBinding.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addBucketConditionalBinding.js,samples/README.md) |
|
||||||
|
| Add Bucket Default Owner Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addBucketDefaultOwnerAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addBucketDefaultOwnerAcl.js,samples/README.md) |
|
||||||
|
| Add Bucket Iam Member | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addBucketIamMember.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addBucketIamMember.js,samples/README.md) |
|
||||||
|
| Storage Add Bucket Label. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addBucketLabel.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addBucketLabel.js,samples/README.md) |
|
||||||
|
| Add Bucket Owner Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addBucketOwnerAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addBucketOwnerAcl.js,samples/README.md) |
|
||||||
|
| Bucket Website Configuration. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addBucketWebsiteConfiguration.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addBucketWebsiteConfiguration.js,samples/README.md) |
|
||||||
|
| Add File Owner Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/addFileOwnerAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/addFileOwnerAcl.js,samples/README.md) |
|
||||||
|
| Storage Get Bucket Metadata. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/bucketMetadata.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/bucketMetadata.js,samples/README.md) |
|
||||||
|
| Change Bucket's Default Storage Class. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/changeDefaultStorageClass.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/changeDefaultStorageClass.js,samples/README.md) |
|
||||||
|
| Storage File Convert CSEK to CMEK. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/changeFileCSEKToCMEK.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/changeFileCSEKToCMEK.js,samples/README.md) |
|
||||||
|
| Storage Combine files. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/composeFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/composeFile.js,samples/README.md) |
|
||||||
|
| Storage Configure Bucket Cors. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/configureBucketCors.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/configureBucketCors.js,samples/README.md) |
|
||||||
|
| Configure Retries | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/configureRetries.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/configureRetries.js,samples/README.md) |
|
||||||
|
| Copy File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/copyFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/copyFile.js,samples/README.md) |
|
||||||
|
| Copy Old Version Of File. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/copyOldVersionOfFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/copyOldVersionOfFile.js,samples/README.md) |
|
||||||
|
| Create a Dual-Region Bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createBucketWithDualRegion.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createBucketWithDualRegion.js,samples/README.md) |
|
||||||
|
| Create a hierarchical namespace enabled bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createBucketWithHierarchicalNamespace.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createBucketWithHierarchicalNamespace.js,samples/README.md) |
|
||||||
|
| Create a Bucket with object retention enabled. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createBucketWithObjectRetention.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createBucketWithObjectRetention.js,samples/README.md) |
|
||||||
|
| Create Bucket With Storage Class and Location. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createBucketWithStorageClassAndLocation.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createBucketWithStorageClassAndLocation.js,samples/README.md) |
|
||||||
|
| Create Bucket With Turbo Replication | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createBucketWithTurboReplication.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createBucketWithTurboReplication.js,samples/README.md) |
|
||||||
|
| Create New Bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createNewBucket.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createNewBucket.js,samples/README.md) |
|
||||||
|
| Create Notification | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/createNotification.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/createNotification.js,samples/README.md) |
|
||||||
|
| Delete Bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/deleteBucket.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/deleteBucket.js,samples/README.md) |
|
||||||
|
| Delete File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/deleteFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/deleteFile.js,samples/README.md) |
|
||||||
|
| Delete Notification | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/deleteNotification.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/deleteNotification.js,samples/README.md) |
|
||||||
|
| Delete Old Version Of File. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/deleteOldVersionOfFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/deleteOldVersionOfFile.js,samples/README.md) |
|
||||||
|
| Disable Bucket Lifecycle Management | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/disableBucketLifecycleManagement.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/disableBucketLifecycleManagement.js,samples/README.md) |
|
||||||
|
| Storage Disable Bucket Versioning. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/disableBucketVersioning.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/disableBucketVersioning.js,samples/README.md) |
|
||||||
|
| Disable Default Event Based Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/disableDefaultEventBasedHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/disableDefaultEventBasedHold.js,samples/README.md) |
|
||||||
|
| Disable Requester Pays | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/disableRequesterPays.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/disableRequesterPays.js,samples/README.md) |
|
||||||
|
| Disable Uniform Bucket Level Access | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/disableUniformBucketLevelAccess.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/disableUniformBucketLevelAccess.js,samples/README.md) |
|
||||||
|
| Download Byte Range | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadByteRange.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadByteRange.js,samples/README.md) |
|
||||||
|
| Download Encrypted File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadEncryptedFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadEncryptedFile.js,samples/README.md) |
|
||||||
|
| Download File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadFile.js,samples/README.md) |
|
||||||
|
| Download a File in Chunks With Transfer Manager | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadFileInChunksWithTransferManager.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadFileInChunksWithTransferManager.js,samples/README.md) |
|
||||||
|
| Download File Using Requester Pays | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadFileUsingRequesterPays.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadFileUsingRequesterPays.js,samples/README.md) |
|
||||||
|
| Download Folder With Transfer Manager | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadFolderWithTransferManager.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadFolderWithTransferManager.js,samples/README.md) |
|
||||||
|
| Download Into Memory | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadIntoMemory.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadIntoMemory.js,samples/README.md) |
|
||||||
|
| Download Many Files With Transfer Manager | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadManyFilesWithTransferManager.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadManyFilesWithTransferManager.js,samples/README.md) |
|
||||||
|
| Storage Download Public File. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/downloadPublicFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/downloadPublicFile.js,samples/README.md) |
|
||||||
|
| Enable Bucket Lifecycle Management | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/enableBucketLifecycleManagement.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/enableBucketLifecycleManagement.js,samples/README.md) |
|
||||||
|
| Storage Enable Bucket Versioning. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/enableBucketVersioning.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/enableBucketVersioning.js,samples/README.md) |
|
||||||
|
| Enable Default Event Based Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/enableDefaultEventBasedHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/enableDefaultEventBasedHold.js,samples/README.md) |
|
||||||
|
| Enable Default KMS Key | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/enableDefaultKMSKey.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/enableDefaultKMSKey.js,samples/README.md) |
|
||||||
|
| Enable Requester Pays | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/enableRequesterPays.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/enableRequesterPays.js,samples/README.md) |
|
||||||
|
| Enable Uniform Bucket Level Access | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/enableUniformBucketLevelAccess.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/enableUniformBucketLevelAccess.js,samples/README.md) |
|
||||||
|
| Change File's Storage Class. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/fileChangeStorageClass.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/fileChangeStorageClass.js,samples/README.md) |
|
||||||
|
| Storage Set File Metadata. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/fileSetMetadata.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/fileSetMetadata.js,samples/README.md) |
|
||||||
|
| Generate Encryption Key | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/generateEncryptionKey.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/generateEncryptionKey.js,samples/README.md) |
|
||||||
|
| Generate Signed Url | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/generateSignedUrl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/generateSignedUrl.js,samples/README.md) |
|
||||||
|
| Generate V4 Read Signed Url | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/generateV4ReadSignedUrl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/generateV4ReadSignedUrl.js,samples/README.md) |
|
||||||
|
| Generate V4 Signed Policy | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/generateV4SignedPolicy.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/generateV4SignedPolicy.js,samples/README.md) |
|
||||||
|
| Generate V4 Upload Signed Url | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/generateV4UploadSignedUrl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/generateV4UploadSignedUrl.js,samples/README.md) |
|
||||||
|
| Get Autoclass | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getAutoclass.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getAutoclass.js,samples/README.md) |
|
||||||
|
| Get Default Event Based Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getDefaultEventBasedHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getDefaultEventBasedHold.js,samples/README.md) |
|
||||||
|
| Get Metadata | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getMetadata.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getMetadata.js,samples/README.md) |
|
||||||
|
| Get Metadata Notifications | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getMetadataNotifications.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getMetadataNotifications.js,samples/README.md) |
|
||||||
|
| Get Public Access Prevention | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getPublicAccessPrevention.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getPublicAccessPrevention.js,samples/README.md) |
|
||||||
|
| Get RPO | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getRPO.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getRPO.js,samples/README.md) |
|
||||||
|
| Get Requester Pays Status | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getRequesterPaysStatus.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getRequesterPaysStatus.js,samples/README.md) |
|
||||||
|
| Get Retention Policy | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getRetentionPolicy.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getRetentionPolicy.js,samples/README.md) |
|
||||||
|
| Storage Get Service Account. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getServiceAccount.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getServiceAccount.js,samples/README.md) |
|
||||||
|
| Get Soft Deleted Bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getSoftDeletedBucket.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getSoftDeletedBucket.js,samples/README.md) |
|
||||||
|
| Get Uniform Bucket Level Access | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/getUniformBucketLevelAccess.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/getUniformBucketLevelAccess.js,samples/README.md) |
|
||||||
|
| Activate HMAC SA Key. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/hmacKeyActivate.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/hmacKeyActivate.js,samples/README.md) |
|
||||||
|
| Create HMAC SA Key. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/hmacKeyCreate.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/hmacKeyCreate.js,samples/README.md) |
|
||||||
|
| Deactivate HMAC SA Key. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/hmacKeyDeactivate.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/hmacKeyDeactivate.js,samples/README.md) |
|
||||||
|
| Delete HMAC SA Key. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/hmacKeyDelete.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/hmacKeyDelete.js,samples/README.md) |
|
||||||
|
| Get HMAC SA Key Metadata. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/hmacKeyGet.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/hmacKeyGet.js,samples/README.md) |
|
||||||
|
| List HMAC SA Keys Metadata. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/hmacKeysList.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/hmacKeysList.js,samples/README.md) |
|
||||||
|
| List Buckets | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listBuckets.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listBuckets.js,samples/README.md) |
|
||||||
|
| List Files | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listFiles.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listFiles.js,samples/README.md) |
|
||||||
|
| List Files By Prefix | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listFilesByPrefix.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listFilesByPrefix.js,samples/README.md) |
|
||||||
|
| List Files Paginate | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listFilesPaginate.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listFilesPaginate.js,samples/README.md) |
|
||||||
|
| List Files with Old Versions. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listFilesWithOldVersions.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listFilesWithOldVersions.js,samples/README.md) |
|
||||||
|
| List Notifications | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listNotifications.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listNotifications.js,samples/README.md) |
|
||||||
|
| List Soft Deleted Bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/listSoftDeletedBucket.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/listSoftDeletedBucket.js,samples/README.md) |
|
||||||
|
| Lock Retention Policy | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/lockRetentionPolicy.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/lockRetentionPolicy.js,samples/README.md) |
|
||||||
|
| Storage Make Bucket Public. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/makeBucketPublic.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/makeBucketPublic.js,samples/README.md) |
|
||||||
|
| Make Public | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/makePublic.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/makePublic.js,samples/README.md) |
|
||||||
|
| Move File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/moveFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/moveFile.js,samples/README.md) |
|
||||||
|
| Move File Atomic | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/moveFileAtomic.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/moveFileAtomic.js,samples/README.md) |
|
||||||
|
| Print Bucket Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/printBucketAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/printBucketAcl.js,samples/README.md) |
|
||||||
|
| Print Bucket Acl For User | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/printBucketAclForUser.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/printBucketAclForUser.js,samples/README.md) |
|
||||||
|
| Print File Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/printFileAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/printFileAcl.js,samples/README.md) |
|
||||||
|
| Print File Acl For User | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/printFileAclForUser.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/printFileAclForUser.js,samples/README.md) |
|
||||||
|
| Quickstart | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/quickstart.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/quickstart.js,samples/README.md) |
|
||||||
|
| Release Event Based Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/releaseEventBasedHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/releaseEventBasedHold.js,samples/README.md) |
|
||||||
|
| Release Temporary Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/releaseTemporaryHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/releaseTemporaryHold.js,samples/README.md) |
|
||||||
|
| Remove Bucket Conditional Binding | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeBucketConditionalBinding.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeBucketConditionalBinding.js,samples/README.md) |
|
||||||
|
| Storage Remove Bucket Cors Configuration. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeBucketCors.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeBucketCors.js,samples/README.md) |
|
||||||
|
| Remove Bucket Default Owner | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeBucketDefaultOwner.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeBucketDefaultOwner.js,samples/README.md) |
|
||||||
|
| Remove Bucket Iam Member | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeBucketIamMember.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeBucketIamMember.js,samples/README.md) |
|
||||||
|
| Storage Remove Bucket Label. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeBucketLabel.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeBucketLabel.js,samples/README.md) |
|
||||||
|
| Remove Bucket Owner Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeBucketOwnerAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeBucketOwnerAcl.js,samples/README.md) |
|
||||||
|
| Remove Default KMS Key. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeDefaultKMSKey.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeDefaultKMSKey.js,samples/README.md) |
|
||||||
|
| Remove File Owner Acl | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeFileOwnerAcl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeFileOwnerAcl.js,samples/README.md) |
|
||||||
|
| Remove Retention Policy | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/removeRetentionPolicy.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/removeRetentionPolicy.js,samples/README.md) |
|
||||||
|
| Rename File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/renameFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/renameFile.js,samples/README.md) |
|
||||||
|
| Restore Soft Deleted Bucket | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/restoreSoftDeletedBucket.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/restoreSoftDeletedBucket.js,samples/README.md) |
|
||||||
|
| Rotate Encryption Key | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/rotateEncryptionKey.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/rotateEncryptionKey.js,samples/README.md) |
|
||||||
|
| Set Autoclass | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setAutoclass.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setAutoclass.js,samples/README.md) |
|
||||||
|
| Set Client Endpoint | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setClientEndpoint.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setClientEndpoint.js,samples/README.md) |
|
||||||
|
| Set Event Based Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setEventBasedHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setEventBasedHold.js,samples/README.md) |
|
||||||
|
| Set the object retention policy of a File. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setObjectRetentionPolicy.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setObjectRetentionPolicy.js,samples/README.md) |
|
||||||
|
| Set Public Access Prevention Enforced | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setPublicAccessPreventionEnforced.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setPublicAccessPreventionEnforced.js,samples/README.md) |
|
||||||
|
| Set Public Access Prevention Inherited | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setPublicAccessPreventionInherited.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setPublicAccessPreventionInherited.js,samples/README.md) |
|
||||||
|
| Set RPO Async Turbo | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setRPOAsyncTurbo.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setRPOAsyncTurbo.js,samples/README.md) |
|
||||||
|
| Set RPO Default | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setRPODefault.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setRPODefault.js,samples/README.md) |
|
||||||
|
| Set Retention Policy | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setRetentionPolicy.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setRetentionPolicy.js,samples/README.md) |
|
||||||
|
| Set Temporary Hold | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/setTemporaryHold.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/setTemporaryHold.js,samples/README.md) |
|
||||||
|
| Stream File Download | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/streamFileDownload.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/streamFileDownload.js,samples/README.md) |
|
||||||
|
| Stream File Upload | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/streamFileUpload.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/streamFileUpload.js,samples/README.md) |
|
||||||
|
| Upload a directory to a bucket. | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadDirectory.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadDirectory.js,samples/README.md) |
|
||||||
|
| Upload Directory With Transfer Manager | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadDirectoryWithTransferManager.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadDirectoryWithTransferManager.js,samples/README.md) |
|
||||||
|
| Upload Encrypted File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadEncryptedFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadEncryptedFile.js,samples/README.md) |
|
||||||
|
| Upload File | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadFile.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadFile.js,samples/README.md) |
|
||||||
|
| Upload a File in Chunks With Transfer Manager | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadFileInChunksWithTransferManager.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadFileInChunksWithTransferManager.js,samples/README.md) |
|
||||||
|
| Upload File With Kms Key | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadFileWithKmsKey.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadFileWithKmsKey.js,samples/README.md) |
|
||||||
|
| Upload From Memory | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadFromMemory.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadFromMemory.js,samples/README.md) |
|
||||||
|
| Upload Many Files With Transfer Manager | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadManyFilesWithTransferManager.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadManyFilesWithTransferManager.js,samples/README.md) |
|
||||||
|
| Upload Without Authentication | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadWithoutAuthentication.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadWithoutAuthentication.js,samples/README.md) |
|
||||||
|
| Upload Without Authentication Signed Url | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/uploadWithoutAuthenticationSignedUrl.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/uploadWithoutAuthenticationSignedUrl.js,samples/README.md) |
|
||||||
|
| View Bucket Iam Members | [source code](https://github.com/googleapis/nodejs-storage/blob/main/samples/viewBucketIamMembers.js) | [![Open in Cloud Shell][shell_img]](https://console.cloud.google.com/cloudshell/open?git_repo=https://github.com/googleapis/nodejs-storage&page=editor&open_in_editor=samples/viewBucketIamMembers.js,samples/README.md) |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
The [Google Cloud Storage Node.js Client API Reference][client-docs] documentation
|
||||||
|
also contains samples.
|
||||||
|
|
||||||
|
## Supported Node.js Versions
|
||||||
|
|
||||||
|
Our client libraries follow the [Node.js release schedule](https://github.com/nodejs/release#release-schedule).
|
||||||
|
Libraries are compatible with all current _active_ and _maintenance_ versions of
|
||||||
|
Node.js.
|
||||||
|
If you are using an end-of-life version of Node.js, we recommend that you update
|
||||||
|
as soon as possible to an actively supported LTS version.
|
||||||
|
|
||||||
|
Google's client libraries support legacy versions of Node.js runtimes on a
|
||||||
|
best-efforts basis with the following warnings:
|
||||||
|
|
||||||
|
* Legacy versions are not tested in continuous integration.
|
||||||
|
* Some security patches and features cannot be backported.
|
||||||
|
* Dependencies cannot be kept up-to-date.
|
||||||
|
|
||||||
|
Client libraries targeting some end-of-life versions of Node.js are available, and
|
||||||
|
can be installed through npm [dist-tags](https://docs.npmjs.com/cli/dist-tag).
|
||||||
|
The dist-tags follow the naming convention `legacy-(version)`.
|
||||||
|
For example, `npm install @google-cloud/storage@legacy-8` installs client libraries
|
||||||
|
for versions compatible with Node.js 8.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
This library follows [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This library is considered to be **stable**. The code surface will not change in backwards-incompatible ways
|
||||||
|
unless absolutely necessary (e.g. because of critical security issues) or with
|
||||||
|
an extensive deprecation period. Issues and requests against **stable** libraries
|
||||||
|
are addressed with the highest priority.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
More Information: [Google Cloud Platform Launch Stages][launch_stages]
|
||||||
|
|
||||||
|
[launch_stages]: https://cloud.google.com/terms/launch-stages
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions welcome! See the [Contributing Guide](https://github.com/googleapis/nodejs-storage/blob/main/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
Please note that this `README.md`, the `samples/README.md`,
|
||||||
|
and a variety of configuration files in this repository (including `.nycrc` and `tsconfig.json`)
|
||||||
|
are generated from a central template. To edit one of these files, make an edit
|
||||||
|
to its templates in
|
||||||
|
[directory](https://github.com/googleapis/synthtool).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache Version 2.0
|
||||||
|
|
||||||
|
See [LICENSE](https://github.com/googleapis/nodejs-storage/blob/main/LICENSE)
|
||||||
|
|
||||||
|
[client-docs]: https://cloud.google.com/nodejs/docs/reference/storage/latest
|
||||||
|
[product-docs]: https://cloud.google.com/storage
|
||||||
|
[shell_img]: https://gstatic.com/cloudssh/images/open-btn.png
|
||||||
|
[projects]: https://console.cloud.google.com/project
|
||||||
|
[billing]: https://support.google.com/cloud/answer/6293499#enable-billing
|
||||||
|
[enable_api]: https://console.cloud.google.com/flows/enableapi?apiid=storage-api.googleapis.com
|
||||||
|
[auth]: https://cloud.google.com/docs/authentication/external/set-up-adc-local
|
131
em2rp/node_modules/@google-cloud/storage/package.json
generated
vendored
Normal file
131
em2rp/node_modules/@google-cloud/storage/package.json
generated
vendored
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
{
|
||||||
|
"name": "@google-cloud/storage",
|
||||||
|
"description": "Cloud Storage Client Library for Node.js",
|
||||||
|
"version": "7.16.0",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"author": "Google Inc.",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"repository": "googleapis/nodejs-storage",
|
||||||
|
"main": "./build/cjs/src/index.js",
|
||||||
|
"types": "./build/cjs/src/index.d.ts",
|
||||||
|
"type": "module",
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": {
|
||||||
|
"types": "./build/esm/src/index.d.ts",
|
||||||
|
"default": "./build/esm/src/index.js"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"types": "./build/cjs/src/index.d.ts",
|
||||||
|
"default": "./build/cjs/src/index.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"build/cjs/src",
|
||||||
|
"build/cjs/package.json",
|
||||||
|
"!build/cjs/src/**/*.map",
|
||||||
|
"build/esm/src",
|
||||||
|
"!build/esm/src/**/*.map"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"google apis client",
|
||||||
|
"google api client",
|
||||||
|
"google apis",
|
||||||
|
"google api",
|
||||||
|
"google",
|
||||||
|
"google cloud platform",
|
||||||
|
"google cloud",
|
||||||
|
"cloud",
|
||||||
|
"google storage",
|
||||||
|
"storage"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"all-test": "npm test && npm run system-test && npm run samples-test",
|
||||||
|
"benchwrapper": "node bin/benchwrapper.js",
|
||||||
|
"check": "gts check",
|
||||||
|
"clean": "rm -rf build/",
|
||||||
|
"compile:cjs": "tsc -p ./tsconfig.cjs.json",
|
||||||
|
"compile:esm": "tsc -p .",
|
||||||
|
"compile": "npm run compile:cjs && npm run compile:esm",
|
||||||
|
"conformance-test": "mocha --parallel build/cjs/conformance-test/ --require build/cjs/conformance-test/globalHooks.js",
|
||||||
|
"docs-test": "linkinator docs",
|
||||||
|
"docs": "jsdoc -c .jsdoc.json",
|
||||||
|
"fix": "gts fix",
|
||||||
|
"lint": "gts check",
|
||||||
|
"postcompile": "cp ./src/package-json-helper.cjs ./build/cjs/src && cp ./src/package-json-helper.cjs ./build/esm/src",
|
||||||
|
"postcompile:cjs": "babel --plugins gapic-tools/build/src/replaceImportMetaUrl,gapic-tools/build/src/toggleESMFlagVariable build/cjs/src/util.js -o build/cjs/src/util.js && cp internal-tooling/helpers/package.cjs.json build/cjs/package.json",
|
||||||
|
"precompile": "rm -rf build/",
|
||||||
|
"preconformance-test": "npm run compile:cjs -- --sourceMap",
|
||||||
|
"predocs-test": "npm run docs",
|
||||||
|
"predocs": "npm run compile:cjs -- --sourceMap",
|
||||||
|
"prelint": "cd samples; npm link ../; npm install",
|
||||||
|
"prepare": "npm run compile",
|
||||||
|
"presystem-test:esm": "npm run compile:esm",
|
||||||
|
"presystem-test": "npm run compile -- --sourceMap",
|
||||||
|
"pretest": "npm run compile -- --sourceMap",
|
||||||
|
"samples-test": "npm link && cd samples/ && npm link ../ && npm test && cd ../",
|
||||||
|
"system-test:esm": "mocha build/esm/system-test --timeout 600000 --exit",
|
||||||
|
"system-test": "mocha build/cjs/system-test --timeout 600000 --exit",
|
||||||
|
"test": "c8 mocha build/cjs/test"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@google-cloud/paginator": "^5.0.0",
|
||||||
|
"@google-cloud/projectify": "^4.0.0",
|
||||||
|
"@google-cloud/promisify": "<4.1.0",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"async-retry": "^1.3.3",
|
||||||
|
"duplexify": "^4.1.3",
|
||||||
|
"fast-xml-parser": "^4.4.1",
|
||||||
|
"gaxios": "^6.0.2",
|
||||||
|
"google-auth-library": "^9.6.3",
|
||||||
|
"html-entities": "^2.5.2",
|
||||||
|
"mime": "^3.0.0",
|
||||||
|
"p-limit": "^3.0.1",
|
||||||
|
"retry-request": "^7.0.0",
|
||||||
|
"teeny-request": "^9.0.0",
|
||||||
|
"uuid": "^8.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.22.10",
|
||||||
|
"@babel/core": "^7.22.11",
|
||||||
|
"@google-cloud/pubsub": "^4.0.0",
|
||||||
|
"@grpc/grpc-js": "^1.0.3",
|
||||||
|
"@grpc/proto-loader": "^0.7.0",
|
||||||
|
"@types/async-retry": "^1.4.3",
|
||||||
|
"@types/duplexify": "^3.6.4",
|
||||||
|
"@types/mime": "^3.0.0",
|
||||||
|
"@types/mocha": "^9.1.1",
|
||||||
|
"@types/mockery": "^1.4.29",
|
||||||
|
"@types/node": "^22.0.0",
|
||||||
|
"@types/node-fetch": "^2.1.3",
|
||||||
|
"@types/proxyquire": "^1.3.28",
|
||||||
|
"@types/request": "^2.48.4",
|
||||||
|
"@types/sinon": "^17.0.0",
|
||||||
|
"@types/tmp": "0.2.6",
|
||||||
|
"@types/uuid": "^8.0.0",
|
||||||
|
"@types/yargs": "^17.0.10",
|
||||||
|
"c8": "^9.0.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
|
"gapic-tools": "^0.4.0",
|
||||||
|
"gts": "^5.0.0",
|
||||||
|
"jsdoc": "^4.0.0",
|
||||||
|
"jsdoc-fresh": "^3.0.0",
|
||||||
|
"jsdoc-region-tag": "^3.0.0",
|
||||||
|
"linkinator": "^3.0.0",
|
||||||
|
"mocha": "^9.2.2",
|
||||||
|
"mockery": "^2.1.0",
|
||||||
|
"nock": "~13.5.0",
|
||||||
|
"node-fetch": "^2.6.7",
|
||||||
|
"pack-n-play": "^2.0.0",
|
||||||
|
"proxyquire": "^2.1.3",
|
||||||
|
"sinon": "^18.0.0",
|
||||||
|
"nise": "6.0.0",
|
||||||
|
"path-to-regexp": "6.3.0",
|
||||||
|
"tmp": "^0.2.0",
|
||||||
|
"typescript": "^5.1.6",
|
||||||
|
"yargs": "^17.3.1"
|
||||||
|
}
|
||||||
|
}
|
21
em2rp/node_modules/@tootallnate/once/LICENSE
generated
vendored
Normal file
21
em2rp/node_modules/@tootallnate/once/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Nathan Rajlich
|
||||||
|
|
||||||
|
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.
|
93
em2rp/node_modules/@tootallnate/once/README.md
generated
vendored
Normal file
93
em2rp/node_modules/@tootallnate/once/README.md
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
# @tootallnate/once
|
||||||
|
|
||||||
|
### Creates a Promise that waits for a single event
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install with `npm`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install @tootallnate/once
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### once(emitter: EventEmitter, name: string, opts?: OnceOptions): Promise<[...Args]>
|
||||||
|
|
||||||
|
Creates a Promise that waits for event `name` to occur on `emitter`, and resolves
|
||||||
|
the promise with an array of the values provided to the event handler. If an
|
||||||
|
`error` event occurs before the event specified by `name`, then the Promise is
|
||||||
|
rejected with the error argument.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import once from '@tootallnate/once';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
|
||||||
|
const emitter = new EventEmitter();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
emitter.emit('foo', 'bar');
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
const [result] = await once(emitter, 'foo');
|
||||||
|
console.log({ result });
|
||||||
|
// { result: 'bar' }
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Promise Strong Typing
|
||||||
|
|
||||||
|
The main feature that this module provides over other "once" implementations is that
|
||||||
|
the Promise that is returned is _**strongly typed**_ based on the type of `emitter`
|
||||||
|
and the `name` of the event. Some examples are shown below.
|
||||||
|
|
||||||
|
_The process "exit" event contains a single number for exit code:_
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const [code] = await once(process, 'exit');
|
||||||
|
// ^ number
|
||||||
|
```
|
||||||
|
_A child process "exit" event contains either an exit code or a signal:_
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const child = spawn('echo', []);
|
||||||
|
const [code, signal] = await once(child, 'exit');
|
||||||
|
// ^ number | null
|
||||||
|
// ^ string | null
|
||||||
|
```
|
||||||
|
|
||||||
|
_A forked child process "message" event is type `any`, so you can cast the Promise directly:_
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const child = fork('file.js');
|
||||||
|
|
||||||
|
// With `await`
|
||||||
|
const [message, _]: [WorkerPayload, unknown] = await once(child, 'message');
|
||||||
|
|
||||||
|
// With Promise
|
||||||
|
const messagePromise: Promise<[WorkerPayload, unknown]> = once(child, 'message');
|
||||||
|
|
||||||
|
// Better yet would be to leave it as `any`, and validate the payload
|
||||||
|
// at runtime with i.e. `ajv` + `json-schema-to-typescript`
|
||||||
|
```
|
||||||
|
|
||||||
|
_If the TypeScript definition does not contain an overload for the specified event name, then the Promise will have type `unknown[]` and your code will need to narrow the result manually:_
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface CustomEmitter extends EventEmitter {
|
||||||
|
on(name: 'foo', listener: (a: string, b: number) => void): this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emitter: CustomEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
// "foo" event is a defined overload, so it's properly typed
|
||||||
|
const fooPromise = once(emitter, 'foo');
|
||||||
|
// ^ Promise<[a: string, b: number]>
|
||||||
|
|
||||||
|
// "bar" event in not a defined overload, so it gets `unknown[]`
|
||||||
|
const barPromise = once(emitter, 'bar');
|
||||||
|
// ^ Promise<unknown[]>
|
||||||
|
```
|
||||||
|
|
||||||
|
### OnceOptions
|
||||||
|
|
||||||
|
- `signal` - `AbortSignal` instance to unbind event handlers before the Promise has been fulfilled.
|
7
em2rp/node_modules/@tootallnate/once/dist/index.d.ts
generated
vendored
Normal file
7
em2rp/node_modules/@tootallnate/once/dist/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { EventNames, EventListenerParameters, AbortSignal } from './types';
|
||||||
|
export interface OnceOptions {
|
||||||
|
signal?: AbortSignal;
|
||||||
|
}
|
||||||
|
export default function once<Emitter extends EventEmitter, Event extends EventNames<Emitter>>(emitter: Emitter, name: Event, { signal }?: OnceOptions): Promise<EventListenerParameters<Emitter, Event>>;
|
24
em2rp/node_modules/@tootallnate/once/dist/index.js
generated
vendored
Normal file
24
em2rp/node_modules/@tootallnate/once/dist/index.js
generated
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
function once(emitter, name, { signal } = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
function cleanup() {
|
||||||
|
signal === null || signal === void 0 ? void 0 : signal.removeEventListener('abort', cleanup);
|
||||||
|
emitter.removeListener(name, onEvent);
|
||||||
|
emitter.removeListener('error', onError);
|
||||||
|
}
|
||||||
|
function onEvent(...args) {
|
||||||
|
cleanup();
|
||||||
|
resolve(args);
|
||||||
|
}
|
||||||
|
function onError(err) {
|
||||||
|
cleanup();
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
signal === null || signal === void 0 ? void 0 : signal.addEventListener('abort', cleanup);
|
||||||
|
emitter.on(name, onEvent);
|
||||||
|
emitter.on('error', onError);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.default = once;
|
||||||
|
//# sourceMappingURL=index.js.map
|
1
em2rp/node_modules/@tootallnate/once/dist/index.js.map
generated
vendored
Normal file
1
em2rp/node_modules/@tootallnate/once/dist/index.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAOA,SAAwB,IAAI,CAI3B,OAAgB,EAChB,IAAW,EACX,EAAE,MAAM,KAAkB,EAAE;IAE5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,SAAS,OAAO;YACf,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAC9C,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtC,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1C,CAAC;QACD,SAAS,OAAO,CAAC,GAAG,IAAW;YAC9B,OAAO,EAAE,CAAC;YACV,OAAO,CAAC,IAA+C,CAAC,CAAC;QAC1D,CAAC;QACD,SAAS,OAAO,CAAC,GAAU;YAC1B,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,GAAG,CAAC,CAAC;QACb,CAAC;QACD,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACJ,CAAC;AA1BD,uBA0BC"}
|
231
em2rp/node_modules/@tootallnate/once/dist/overloaded-parameters.d.ts
generated
vendored
Normal file
231
em2rp/node_modules/@tootallnate/once/dist/overloaded-parameters.d.ts
generated
vendored
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
export declare type OverloadedParameters<T> = T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
(...args: infer A15): any;
|
||||||
|
(...args: infer A16): any;
|
||||||
|
(...args: infer A17): any;
|
||||||
|
(...args: infer A18): any;
|
||||||
|
(...args: infer A19): any;
|
||||||
|
(...args: infer A20): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 | A16 | A17 | A18 | A19 | A20 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
(...args: infer A15): any;
|
||||||
|
(...args: infer A16): any;
|
||||||
|
(...args: infer A17): any;
|
||||||
|
(...args: infer A18): any;
|
||||||
|
(...args: infer A19): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 | A16 | A17 | A18 | A19 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
(...args: infer A15): any;
|
||||||
|
(...args: infer A16): any;
|
||||||
|
(...args: infer A17): any;
|
||||||
|
(...args: infer A18): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 | A16 | A17 | A18 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
(...args: infer A15): any;
|
||||||
|
(...args: infer A16): any;
|
||||||
|
(...args: infer A17): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 | A16 | A17 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
(...args: infer A15): any;
|
||||||
|
(...args: infer A16): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 | A16 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
(...args: infer A15): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 | A15 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
(...args: infer A14): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 | A14 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
(...args: infer A13): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 | A13 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
(...args: infer A12): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 | A12 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
(...args: infer A11): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 | A11 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
(...args: infer A10): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | A10 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
(...args: infer A9): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
(...args: infer A8): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
(...args: infer A7): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 | A7 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
(...args: infer A6): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 | A6 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
(...args: infer A5): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 | A5 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
(...args: infer A4): any;
|
||||||
|
} ? A1 | A2 | A3 | A4 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
(...args: infer A3): any;
|
||||||
|
} ? A1 | A2 | A3 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
(...args: infer A2): any;
|
||||||
|
} ? A1 | A2 : T extends {
|
||||||
|
(...args: infer A1): any;
|
||||||
|
} ? A1 : any;
|
3
em2rp/node_modules/@tootallnate/once/dist/overloaded-parameters.js
generated
vendored
Normal file
3
em2rp/node_modules/@tootallnate/once/dist/overloaded-parameters.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
//# sourceMappingURL=overloaded-parameters.js.map
|
1
em2rp/node_modules/@tootallnate/once/dist/overloaded-parameters.js.map
generated
vendored
Normal file
1
em2rp/node_modules/@tootallnate/once/dist/overloaded-parameters.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"overloaded-parameters.js","sourceRoot":"","sources":["../src/overloaded-parameters.ts"],"names":[],"mappings":""}
|
17
em2rp/node_modules/@tootallnate/once/dist/types.d.ts
generated
vendored
Normal file
17
em2rp/node_modules/@tootallnate/once/dist/types.d.ts
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/// <reference types="node" />
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { OverloadedParameters } from './overloaded-parameters';
|
||||||
|
export declare type FirstParameter<T> = T extends [infer R, ...any[]] ? R : never;
|
||||||
|
export declare type EventListener<F, T extends string | symbol> = F extends [
|
||||||
|
T,
|
||||||
|
infer R,
|
||||||
|
...any[]
|
||||||
|
] ? R : never;
|
||||||
|
export declare type EventParameters<Emitter extends EventEmitter> = OverloadedParameters<Emitter['on']>;
|
||||||
|
export declare type EventNames<Emitter extends EventEmitter> = FirstParameter<EventParameters<Emitter>>;
|
||||||
|
export declare type EventListenerParameters<Emitter extends EventEmitter, Event extends EventNames<Emitter>> = WithDefault<Parameters<EventListener<EventParameters<Emitter>, Event>>, unknown[]>;
|
||||||
|
export declare type WithDefault<T, D> = [T] extends [never] ? D : T;
|
||||||
|
export interface AbortSignal {
|
||||||
|
addEventListener: (name: string, listener: (...args: any[]) => any) => void;
|
||||||
|
removeEventListener: (name: string, listener: (...args: any[]) => any) => void;
|
||||||
|
}
|
3
em2rp/node_modules/@tootallnate/once/dist/types.js
generated
vendored
Normal file
3
em2rp/node_modules/@tootallnate/once/dist/types.js
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
//# sourceMappingURL=types.js.map
|
1
em2rp/node_modules/@tootallnate/once/dist/types.js.map
generated
vendored
Normal file
1
em2rp/node_modules/@tootallnate/once/dist/types.js.map
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
52
em2rp/node_modules/@tootallnate/once/package.json
generated
vendored
Normal file
52
em2rp/node_modules/@tootallnate/once/package.json
generated
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "@tootallnate/once",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"description": "Creates a Promise that waits for a single event",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"prebuild": "rimraf dist",
|
||||||
|
"build": "tsc",
|
||||||
|
"test": "jest",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/TooTallNate/once.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)",
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/TooTallNate/once/issues"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^27.0.2",
|
||||||
|
"@types/node": "^12.12.11",
|
||||||
|
"abort-controller": "^3.0.0",
|
||||||
|
"jest": "^27.2.1",
|
||||||
|
"rimraf": "^3.0.0",
|
||||||
|
"ts-jest": "^27.0.5",
|
||||||
|
"typescript": "^4.4.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"preset": "ts-jest",
|
||||||
|
"globals": {
|
||||||
|
"ts-jest": {
|
||||||
|
"diagnostics": false,
|
||||||
|
"isolatedModules": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"verbose": false,
|
||||||
|
"testEnvironment": "node",
|
||||||
|
"testMatch": [
|
||||||
|
"<rootDir>/test/**/*.test.ts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
21
em2rp/node_modules/@types/caseless/LICENSE
generated
vendored
Normal file
21
em2rp/node_modules/@types/caseless/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
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
|
48
em2rp/node_modules/@types/caseless/README.md
generated
vendored
Normal file
48
em2rp/node_modules/@types/caseless/README.md
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/caseless`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for caseless (https://github.com/mikeal/caseless).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/caseless.
|
||||||
|
## [index.d.ts](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/caseless/index.d.ts)
|
||||||
|
````ts
|
||||||
|
type KeyType = string;
|
||||||
|
type ValueType = any;
|
||||||
|
type RawDict = object;
|
||||||
|
|
||||||
|
declare function caseless(dict?: RawDict): caseless.Caseless;
|
||||||
|
|
||||||
|
declare namespace caseless {
|
||||||
|
function httpify(resp: object, headers: RawDict): Caseless;
|
||||||
|
|
||||||
|
interface Caseless {
|
||||||
|
set(name: KeyType, value: ValueType, clobber?: boolean): KeyType | false;
|
||||||
|
set(dict: RawDict): void;
|
||||||
|
has(name: KeyType): KeyType | false;
|
||||||
|
get(name: KeyType): ValueType | undefined;
|
||||||
|
swap(name: KeyType): void;
|
||||||
|
del(name: KeyType): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Httpified {
|
||||||
|
headers: RawDict;
|
||||||
|
setHeader(name: KeyType, value: ValueType, clobber?: boolean): KeyType | false;
|
||||||
|
setHeader(dict: RawDict): void;
|
||||||
|
hasHeader(name: KeyType): KeyType | false;
|
||||||
|
getHeader(name: KeyType): ValueType | undefined;
|
||||||
|
removeHeader(name: KeyType): boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = caseless;
|
||||||
|
|
||||||
|
````
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Mon, 06 Nov 2023 22:41:05 GMT
|
||||||
|
* Dependencies: none
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [downace](https://github.com/downace), [Matt R. Wilson](https://github.com/mastermatt), and [Emily Klassen](https://github.com/forivall).
|
29
em2rp/node_modules/@types/caseless/index.d.ts
generated
vendored
Normal file
29
em2rp/node_modules/@types/caseless/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
type KeyType = string;
|
||||||
|
type ValueType = any;
|
||||||
|
type RawDict = object;
|
||||||
|
|
||||||
|
declare function caseless(dict?: RawDict): caseless.Caseless;
|
||||||
|
|
||||||
|
declare namespace caseless {
|
||||||
|
function httpify(resp: object, headers: RawDict): Caseless;
|
||||||
|
|
||||||
|
interface Caseless {
|
||||||
|
set(name: KeyType, value: ValueType, clobber?: boolean): KeyType | false;
|
||||||
|
set(dict: RawDict): void;
|
||||||
|
has(name: KeyType): KeyType | false;
|
||||||
|
get(name: KeyType): ValueType | undefined;
|
||||||
|
swap(name: KeyType): void;
|
||||||
|
del(name: KeyType): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Httpified {
|
||||||
|
headers: RawDict;
|
||||||
|
setHeader(name: KeyType, value: ValueType, clobber?: boolean): KeyType | false;
|
||||||
|
setHeader(dict: RawDict): void;
|
||||||
|
hasHeader(name: KeyType): KeyType | false;
|
||||||
|
getHeader(name: KeyType): ValueType | undefined;
|
||||||
|
removeHeader(name: KeyType): boolean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export = caseless;
|
35
em2rp/node_modules/@types/caseless/package.json
generated
vendored
Normal file
35
em2rp/node_modules/@types/caseless/package.json
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"name": "@types/caseless",
|
||||||
|
"version": "0.12.5",
|
||||||
|
"description": "TypeScript definitions for caseless",
|
||||||
|
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/caseless",
|
||||||
|
"license": "MIT",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "downace",
|
||||||
|
"githubUsername": "downace",
|
||||||
|
"url": "https://github.com/downace"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Matt R. Wilson",
|
||||||
|
"githubUsername": "mastermatt",
|
||||||
|
"url": "https://github.com/mastermatt"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Emily Klassen",
|
||||||
|
"githubUsername": "forivall",
|
||||||
|
"url": "https://github.com/forivall"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"main": "",
|
||||||
|
"types": "index.d.ts",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||||
|
"directory": "types/caseless"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"dependencies": {},
|
||||||
|
"typesPublisherContentHash": "89139c26e367c4adc78c0db606bf3e7b208f60498430b2c167551f7169d0b81c",
|
||||||
|
"typeScriptVersion": "4.5"
|
||||||
|
}
|
21
em2rp/node_modules/@types/node/LICENSE
generated
vendored
Normal file
21
em2rp/node_modules/@types/node/LICENSE
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
|
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
|
15
em2rp/node_modules/@types/node/README.md
generated
vendored
Normal file
15
em2rp/node_modules/@types/node/README.md
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Installation
|
||||||
|
> `npm install --save @types/node`
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
This package contains type definitions for node (https://nodejs.org/).
|
||||||
|
|
||||||
|
# Details
|
||||||
|
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node.
|
||||||
|
|
||||||
|
### Additional Details
|
||||||
|
* Last updated: Tue, 20 May 2025 23:02:19 GMT
|
||||||
|
* Dependencies: [undici-types](https://npmjs.com/package/undici-types)
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
These definitions were written by [Microsoft TypeScript](https://github.com/Microsoft), [Alberto Schiabel](https://github.com/jkomyno), [Alvis HT Tang](https://github.com/alvis), [Andrew Makarov](https://github.com/r3nya), [Benjamin Toueg](https://github.com/btoueg), [Chigozirim C.](https://github.com/smac89), [David Junger](https://github.com/touffy), [Deividas Bakanas](https://github.com/DeividasBakanas), [Eugene Y. Q. Shen](https://github.com/eyqs), [Hannes Magnusson](https://github.com/Hannes-Magnusson-CK), [Huw](https://github.com/hoo29), [Kelvin Jin](https://github.com/kjin), [Klaus Meinhardt](https://github.com/ajafff), [Lishude](https://github.com/islishude), [Mariusz Wiktorczyk](https://github.com/mwiktorczyk), [Mohsen Azimi](https://github.com/mohsen1), [Nikita Galkin](https://github.com/galkin), [Parambir Singh](https://github.com/parambirs), [Sebastian Silbermann](https://github.com/eps1lon), [Thomas den Hollander](https://github.com/ThomasdenH), [Wilco Bakker](https://github.com/WilcoBakker), [wwwy3y3](https://github.com/wwwy3y3), [Samuel Ainsworth](https://github.com/samuela), [Kyle Uehlein](https://github.com/kuehlein), [Thanik Bhongbhibhat](https://github.com/bhongy), [Marcin Kopacz](https://github.com/chyzwar), [Trivikram Kamat](https://github.com/trivikr), [Junxiao Shi](https://github.com/yoursunny), [Ilia Baryshnikov](https://github.com/qwelias), [ExE Boss](https://github.com/ExE-Boss), [Piotr Błażejewicz](https://github.com/peterblazejewicz), [Anna Henningsen](https://github.com/addaleax), [Victor Perin](https://github.com/victorperin), [NodeJS Contributors](https://github.com/NodeJS), [Linus Unnebäck](https://github.com/LinusU), [wafuwafu13](https://github.com/wafuwafu13), [Matteo Collina](https://github.com/mcollina), [Dmitry Semigradsky](https://github.com/Semigradsky), and [René](https://github.com/Renegade334).
|
1054
em2rp/node_modules/@types/node/assert.d.ts
generated
vendored
Normal file
1054
em2rp/node_modules/@types/node/assert.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
em2rp/node_modules/@types/node/assert/strict.d.ts
generated
vendored
Normal file
8
em2rp/node_modules/@types/node/assert/strict.d.ts
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
declare module "assert/strict" {
|
||||||
|
import { strict } from "node:assert";
|
||||||
|
export = strict;
|
||||||
|
}
|
||||||
|
declare module "node:assert/strict" {
|
||||||
|
import { strict } from "node:assert";
|
||||||
|
export = strict;
|
||||||
|
}
|
603
em2rp/node_modules/@types/node/async_hooks.d.ts
generated
vendored
Normal file
603
em2rp/node_modules/@types/node/async_hooks.d.ts
generated
vendored
Normal file
@ -0,0 +1,603 @@
|
|||||||
|
/**
|
||||||
|
* We strongly discourage the use of the `async_hooks` API.
|
||||||
|
* Other APIs that can cover most of its use cases include:
|
||||||
|
*
|
||||||
|
* * [`AsyncLocalStorage`](https://nodejs.org/docs/latest-v22.x/api/async_context.html#class-asynclocalstorage) tracks async context
|
||||||
|
* * [`process.getActiveResourcesInfo()`](https://nodejs.org/docs/latest-v22.x/api/process.html#processgetactiveresourcesinfo) tracks active resources
|
||||||
|
*
|
||||||
|
* The `node:async_hooks` module provides an API to track asynchronous resources.
|
||||||
|
* It can be accessed using:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import async_hooks from 'node:async_hooks';
|
||||||
|
* ```
|
||||||
|
* @experimental
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v22.x/lib/async_hooks.js)
|
||||||
|
*/
|
||||||
|
declare module "async_hooks" {
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* import { executionAsyncId } from 'node:async_hooks';
|
||||||
|
* import fs from 'node:fs';
|
||||||
|
*
|
||||||
|
* console.log(executionAsyncId()); // 1 - bootstrap
|
||||||
|
* const path = '.';
|
||||||
|
* fs.open(path, 'r', (err, fd) => {
|
||||||
|
* console.log(executionAsyncId()); // 6 - open()
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The ID returned from `executionAsyncId()` is related to execution timing, not
|
||||||
|
* causality (which is covered by `triggerAsyncId()`):
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const server = net.createServer((conn) => {
|
||||||
|
* // Returns the ID of the server, not of the new connection, because the
|
||||||
|
* // callback runs in the execution scope of the server's MakeCallback().
|
||||||
|
* async_hooks.executionAsyncId();
|
||||||
|
*
|
||||||
|
* }).listen(port, () => {
|
||||||
|
* // Returns the ID of a TickObject (process.nextTick()) because all
|
||||||
|
* // callbacks passed to .listen() are wrapped in a nextTick().
|
||||||
|
* async_hooks.executionAsyncId();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Promise contexts may not get precise `executionAsyncIds` by default.
|
||||||
|
* See the section on [promise execution tracking](https://nodejs.org/docs/latest-v22.x/api/async_hooks.html#promise-execution-tracking).
|
||||||
|
* @since v8.1.0
|
||||||
|
* @return The `asyncId` of the current execution context. Useful to track when something calls.
|
||||||
|
*/
|
||||||
|
function executionAsyncId(): number;
|
||||||
|
/**
|
||||||
|
* Resource objects returned by `executionAsyncResource()` are most often internal
|
||||||
|
* Node.js handle objects with undocumented APIs. Using any functions or properties
|
||||||
|
* on the object is likely to crash your application and should be avoided.
|
||||||
|
*
|
||||||
|
* Using `executionAsyncResource()` in the top-level execution context will
|
||||||
|
* return an empty object as there is no handle or request object to use,
|
||||||
|
* but having an object representing the top-level can be helpful.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { open } from 'node:fs';
|
||||||
|
* import { executionAsyncId, executionAsyncResource } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* console.log(executionAsyncId(), executionAsyncResource()); // 1 {}
|
||||||
|
* open(new URL(import.meta.url), 'r', (err, fd) => {
|
||||||
|
* console.log(executionAsyncId(), executionAsyncResource()); // 7 FSReqWrap
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This can be used to implement continuation local storage without the
|
||||||
|
* use of a tracking `Map` to store the metadata:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { createServer } from 'node:http';
|
||||||
|
* import {
|
||||||
|
* executionAsyncId,
|
||||||
|
* executionAsyncResource,
|
||||||
|
* createHook,
|
||||||
|
* } from 'node:async_hooks';
|
||||||
|
* const sym = Symbol('state'); // Private symbol to avoid pollution
|
||||||
|
*
|
||||||
|
* createHook({
|
||||||
|
* init(asyncId, type, triggerAsyncId, resource) {
|
||||||
|
* const cr = executionAsyncResource();
|
||||||
|
* if (cr) {
|
||||||
|
* resource[sym] = cr[sym];
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* }).enable();
|
||||||
|
*
|
||||||
|
* const server = createServer((req, res) => {
|
||||||
|
* executionAsyncResource()[sym] = { state: req.url };
|
||||||
|
* setTimeout(function() {
|
||||||
|
* res.end(JSON.stringify(executionAsyncResource()[sym]));
|
||||||
|
* }, 100);
|
||||||
|
* }).listen(3000);
|
||||||
|
* ```
|
||||||
|
* @since v13.9.0, v12.17.0
|
||||||
|
* @return The resource representing the current execution. Useful to store data within the resource.
|
||||||
|
*/
|
||||||
|
function executionAsyncResource(): object;
|
||||||
|
/**
|
||||||
|
* ```js
|
||||||
|
* const server = net.createServer((conn) => {
|
||||||
|
* // The resource that caused (or triggered) this callback to be called
|
||||||
|
* // was that of the new connection. Thus the return value of triggerAsyncId()
|
||||||
|
* // is the asyncId of "conn".
|
||||||
|
* async_hooks.triggerAsyncId();
|
||||||
|
*
|
||||||
|
* }).listen(port, () => {
|
||||||
|
* // Even though all callbacks passed to .listen() are wrapped in a nextTick()
|
||||||
|
* // the callback itself exists because the call to the server's .listen()
|
||||||
|
* // was made. So the return value would be the ID of the server.
|
||||||
|
* async_hooks.triggerAsyncId();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Promise contexts may not get valid `triggerAsyncId`s by default. See
|
||||||
|
* the section on [promise execution tracking](https://nodejs.org/docs/latest-v22.x/api/async_hooks.html#promise-execution-tracking).
|
||||||
|
* @return The ID of the resource responsible for calling the callback that is currently being executed.
|
||||||
|
*/
|
||||||
|
function triggerAsyncId(): number;
|
||||||
|
interface HookCallbacks {
|
||||||
|
/**
|
||||||
|
* Called when a class is constructed that has the possibility to emit an asynchronous event.
|
||||||
|
* @param asyncId A unique ID for the async resource
|
||||||
|
* @param type The type of the async resource
|
||||||
|
* @param triggerAsyncId The unique ID of the async resource in whose execution context this async resource was created
|
||||||
|
* @param resource Reference to the resource representing the async operation, needs to be released during destroy
|
||||||
|
*/
|
||||||
|
init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void;
|
||||||
|
/**
|
||||||
|
* When an asynchronous operation is initiated or completes a callback is called to notify the user.
|
||||||
|
* The before callback is called just before said callback is executed.
|
||||||
|
* @param asyncId the unique identifier assigned to the resource about to execute the callback.
|
||||||
|
*/
|
||||||
|
before?(asyncId: number): void;
|
||||||
|
/**
|
||||||
|
* Called immediately after the callback specified in `before` is completed.
|
||||||
|
*
|
||||||
|
* If an uncaught exception occurs during execution of the callback, then `after` will run after the `'uncaughtException'` event is emitted or a `domain`'s handler runs.
|
||||||
|
* @param asyncId the unique identifier assigned to the resource which has executed the callback.
|
||||||
|
*/
|
||||||
|
after?(asyncId: number): void;
|
||||||
|
/**
|
||||||
|
* Called when a promise has resolve() called. This may not be in the same execution id
|
||||||
|
* as the promise itself.
|
||||||
|
* @param asyncId the unique id for the promise that was resolve()d.
|
||||||
|
*/
|
||||||
|
promiseResolve?(asyncId: number): void;
|
||||||
|
/**
|
||||||
|
* Called after the resource corresponding to asyncId is destroyed
|
||||||
|
* @param asyncId a unique ID for the async resource
|
||||||
|
*/
|
||||||
|
destroy?(asyncId: number): void;
|
||||||
|
}
|
||||||
|
interface AsyncHook {
|
||||||
|
/**
|
||||||
|
* Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop.
|
||||||
|
*/
|
||||||
|
enable(): this;
|
||||||
|
/**
|
||||||
|
* Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.
|
||||||
|
*/
|
||||||
|
disable(): this;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Registers functions to be called for different lifetime events of each async
|
||||||
|
* operation.
|
||||||
|
*
|
||||||
|
* The callbacks `init()`/`before()`/`after()`/`destroy()` are called for the
|
||||||
|
* respective asynchronous event during a resource's lifetime.
|
||||||
|
*
|
||||||
|
* All callbacks are optional. For example, if only resource cleanup needs to
|
||||||
|
* be tracked, then only the `destroy` callback needs to be passed. The
|
||||||
|
* specifics of all functions that can be passed to `callbacks` is in the `Hook Callbacks` section.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { createHook } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const asyncHook = createHook({
|
||||||
|
* init(asyncId, type, triggerAsyncId, resource) { },
|
||||||
|
* destroy(asyncId) { },
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The callbacks will be inherited via the prototype chain:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* class MyAsyncCallbacks {
|
||||||
|
* init(asyncId, type, triggerAsyncId, resource) { }
|
||||||
|
* destroy(asyncId) {}
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* class MyAddedCallbacks extends MyAsyncCallbacks {
|
||||||
|
* before(asyncId) { }
|
||||||
|
* after(asyncId) { }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const asyncHook = async_hooks.createHook(new MyAddedCallbacks());
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Because promises are asynchronous resources whose lifecycle is tracked
|
||||||
|
* via the async hooks mechanism, the `init()`, `before()`, `after()`, and`destroy()` callbacks _must not_ be async functions that return promises.
|
||||||
|
* @since v8.1.0
|
||||||
|
* @param callbacks The `Hook Callbacks` to register
|
||||||
|
* @return Instance used for disabling and enabling hooks
|
||||||
|
*/
|
||||||
|
function createHook(callbacks: HookCallbacks): AsyncHook;
|
||||||
|
interface AsyncResourceOptions {
|
||||||
|
/**
|
||||||
|
* The ID of the execution context that created this async event.
|
||||||
|
* @default executionAsyncId()
|
||||||
|
*/
|
||||||
|
triggerAsyncId?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Disables automatic `emitDestroy` when the object is garbage collected.
|
||||||
|
* This usually does not need to be set (even if `emitDestroy` is called
|
||||||
|
* manually), unless the resource's `asyncId` is retrieved and the
|
||||||
|
* sensitive API's `emitDestroy` is called with it.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
requireManualDestroy?: boolean | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The class `AsyncResource` is designed to be extended by the embedder's async
|
||||||
|
* resources. Using this, users can easily trigger the lifetime events of their
|
||||||
|
* own resources.
|
||||||
|
*
|
||||||
|
* The `init` hook will trigger when an `AsyncResource` is instantiated.
|
||||||
|
*
|
||||||
|
* The following is an overview of the `AsyncResource` API.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { AsyncResource, executionAsyncId } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* // AsyncResource() is meant to be extended. Instantiating a
|
||||||
|
* // new AsyncResource() also triggers init. If triggerAsyncId is omitted then
|
||||||
|
* // async_hook.executionAsyncId() is used.
|
||||||
|
* const asyncResource = new AsyncResource(
|
||||||
|
* type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false },
|
||||||
|
* );
|
||||||
|
*
|
||||||
|
* // Run a function in the execution context of the resource. This will
|
||||||
|
* // * establish the context of the resource
|
||||||
|
* // * trigger the AsyncHooks before callbacks
|
||||||
|
* // * call the provided function `fn` with the supplied arguments
|
||||||
|
* // * trigger the AsyncHooks after callbacks
|
||||||
|
* // * restore the original execution context
|
||||||
|
* asyncResource.runInAsyncScope(fn, thisArg, ...args);
|
||||||
|
*
|
||||||
|
* // Call AsyncHooks destroy callbacks.
|
||||||
|
* asyncResource.emitDestroy();
|
||||||
|
*
|
||||||
|
* // Return the unique ID assigned to the AsyncResource instance.
|
||||||
|
* asyncResource.asyncId();
|
||||||
|
*
|
||||||
|
* // Return the trigger ID for the AsyncResource instance.
|
||||||
|
* asyncResource.triggerAsyncId();
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class AsyncResource {
|
||||||
|
/**
|
||||||
|
* AsyncResource() is meant to be extended. Instantiating a
|
||||||
|
* new AsyncResource() also triggers init. If triggerAsyncId is omitted then
|
||||||
|
* async_hook.executionAsyncId() is used.
|
||||||
|
* @param type The type of async event.
|
||||||
|
* @param triggerAsyncId The ID of the execution context that created
|
||||||
|
* this async event (default: `executionAsyncId()`), or an
|
||||||
|
* AsyncResourceOptions object (since v9.3.0)
|
||||||
|
*/
|
||||||
|
constructor(type: string, triggerAsyncId?: number | AsyncResourceOptions);
|
||||||
|
/**
|
||||||
|
* Binds the given function to the current execution context.
|
||||||
|
* @since v14.8.0, v12.19.0
|
||||||
|
* @param fn The function to bind to the current execution context.
|
||||||
|
* @param type An optional name to associate with the underlying `AsyncResource`.
|
||||||
|
*/
|
||||||
|
static bind<Func extends (this: ThisArg, ...args: any[]) => any, ThisArg>(
|
||||||
|
fn: Func,
|
||||||
|
type?: string,
|
||||||
|
thisArg?: ThisArg,
|
||||||
|
): Func;
|
||||||
|
/**
|
||||||
|
* Binds the given function to execute to this `AsyncResource`'s scope.
|
||||||
|
* @since v14.8.0, v12.19.0
|
||||||
|
* @param fn The function to bind to the current `AsyncResource`.
|
||||||
|
*/
|
||||||
|
bind<Func extends (...args: any[]) => any>(fn: Func): Func;
|
||||||
|
/**
|
||||||
|
* Call the provided function with the provided arguments in the execution context
|
||||||
|
* of the async resource. This will establish the context, trigger the AsyncHooks
|
||||||
|
* before callbacks, call the function, trigger the AsyncHooks after callbacks, and
|
||||||
|
* then restore the original execution context.
|
||||||
|
* @since v9.6.0
|
||||||
|
* @param fn The function to call in the execution context of this async resource.
|
||||||
|
* @param thisArg The receiver to be used for the function call.
|
||||||
|
* @param args Optional arguments to pass to the function.
|
||||||
|
*/
|
||||||
|
runInAsyncScope<This, Result>(
|
||||||
|
fn: (this: This, ...args: any[]) => Result,
|
||||||
|
thisArg?: This,
|
||||||
|
...args: any[]
|
||||||
|
): Result;
|
||||||
|
/**
|
||||||
|
* Call all `destroy` hooks. This should only ever be called once. An error will
|
||||||
|
* be thrown if it is called more than once. This **must** be manually called. If
|
||||||
|
* the resource is left to be collected by the GC then the `destroy` hooks will
|
||||||
|
* never be called.
|
||||||
|
* @return A reference to `asyncResource`.
|
||||||
|
*/
|
||||||
|
emitDestroy(): this;
|
||||||
|
/**
|
||||||
|
* @return The unique `asyncId` assigned to the resource.
|
||||||
|
*/
|
||||||
|
asyncId(): number;
|
||||||
|
/**
|
||||||
|
* @return The same `triggerAsyncId` that is passed to the `AsyncResource` constructor.
|
||||||
|
*/
|
||||||
|
triggerAsyncId(): number;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This class creates stores that stay coherent through asynchronous operations.
|
||||||
|
*
|
||||||
|
* While you can create your own implementation on top of the `node:async_hooks` module, `AsyncLocalStorage` should be preferred as it is a performant and memory
|
||||||
|
* safe implementation that involves significant optimizations that are non-obvious
|
||||||
|
* to implement.
|
||||||
|
*
|
||||||
|
* The following example uses `AsyncLocalStorage` to build a simple logger
|
||||||
|
* that assigns IDs to incoming HTTP requests and includes them in messages
|
||||||
|
* logged within each request.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import http from 'node:http';
|
||||||
|
* import { AsyncLocalStorage } from 'node:async_hooks';
|
||||||
|
*
|
||||||
|
* const asyncLocalStorage = new AsyncLocalStorage();
|
||||||
|
*
|
||||||
|
* function logWithId(msg) {
|
||||||
|
* const id = asyncLocalStorage.getStore();
|
||||||
|
* console.log(`${id !== undefined ? id : '-'}:`, msg);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* let idSeq = 0;
|
||||||
|
* http.createServer((req, res) => {
|
||||||
|
* asyncLocalStorage.run(idSeq++, () => {
|
||||||
|
* logWithId('start');
|
||||||
|
* // Imagine any chain of async operations here
|
||||||
|
* setImmediate(() => {
|
||||||
|
* logWithId('finish');
|
||||||
|
* res.end();
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* }).listen(8080);
|
||||||
|
*
|
||||||
|
* http.get('http://localhost:8080');
|
||||||
|
* http.get('http://localhost:8080');
|
||||||
|
* // Prints:
|
||||||
|
* // 0: start
|
||||||
|
* // 1: start
|
||||||
|
* // 0: finish
|
||||||
|
* // 1: finish
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Each instance of `AsyncLocalStorage` maintains an independent storage context.
|
||||||
|
* Multiple instances can safely exist simultaneously without risk of interfering
|
||||||
|
* with each other's data.
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
*/
|
||||||
|
class AsyncLocalStorage<T> {
|
||||||
|
/**
|
||||||
|
* Binds the given function to the current execution context.
|
||||||
|
* @since v19.8.0
|
||||||
|
* @param fn The function to bind to the current execution context.
|
||||||
|
* @return A new function that calls `fn` within the captured execution context.
|
||||||
|
*/
|
||||||
|
static bind<Func extends (...args: any[]) => any>(fn: Func): Func;
|
||||||
|
/**
|
||||||
|
* Captures the current execution context and returns a function that accepts a
|
||||||
|
* function as an argument. Whenever the returned function is called, it
|
||||||
|
* calls the function passed to it within the captured context.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const asyncLocalStorage = new AsyncLocalStorage();
|
||||||
|
* const runInAsyncScope = asyncLocalStorage.run(123, () => AsyncLocalStorage.snapshot());
|
||||||
|
* const result = asyncLocalStorage.run(321, () => runInAsyncScope(() => asyncLocalStorage.getStore()));
|
||||||
|
* console.log(result); // returns 123
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* AsyncLocalStorage.snapshot() can replace the use of AsyncResource for simple
|
||||||
|
* async context tracking purposes, for example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* class Foo {
|
||||||
|
* #runInAsyncScope = AsyncLocalStorage.snapshot();
|
||||||
|
*
|
||||||
|
* get() { return this.#runInAsyncScope(() => asyncLocalStorage.getStore()); }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const foo = asyncLocalStorage.run(123, () => new Foo());
|
||||||
|
* console.log(asyncLocalStorage.run(321, () => foo.get())); // returns 123
|
||||||
|
* ```
|
||||||
|
* @since v19.8.0
|
||||||
|
* @return A new function with the signature `(fn: (...args) : R, ...args) : R`.
|
||||||
|
*/
|
||||||
|
static snapshot(): <R, TArgs extends any[]>(fn: (...args: TArgs) => R, ...args: TArgs) => R;
|
||||||
|
/**
|
||||||
|
* Disables the instance of `AsyncLocalStorage`. All subsequent calls
|
||||||
|
* to `asyncLocalStorage.getStore()` will return `undefined` until `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()` is called again.
|
||||||
|
*
|
||||||
|
* When calling `asyncLocalStorage.disable()`, all current contexts linked to the
|
||||||
|
* instance will be exited.
|
||||||
|
*
|
||||||
|
* Calling `asyncLocalStorage.disable()` is required before the `asyncLocalStorage` can be garbage collected. This does not apply to stores
|
||||||
|
* provided by the `asyncLocalStorage`, as those objects are garbage collected
|
||||||
|
* along with the corresponding async resources.
|
||||||
|
*
|
||||||
|
* Use this method when the `asyncLocalStorage` is not in use anymore
|
||||||
|
* in the current process.
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
disable(): void;
|
||||||
|
/**
|
||||||
|
* Returns the current store.
|
||||||
|
* If called outside of an asynchronous context initialized by
|
||||||
|
* calling `asyncLocalStorage.run()` or `asyncLocalStorage.enterWith()`, it
|
||||||
|
* returns `undefined`.
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
*/
|
||||||
|
getStore(): T | undefined;
|
||||||
|
/**
|
||||||
|
* Runs a function synchronously within a context and returns its
|
||||||
|
* return value. The store is not accessible outside of the callback function.
|
||||||
|
* The store is accessible to any asynchronous operations created within the
|
||||||
|
* callback.
|
||||||
|
*
|
||||||
|
* The optional `args` are passed to the callback function.
|
||||||
|
*
|
||||||
|
* If the callback function throws an error, the error is thrown by `run()` too.
|
||||||
|
* The stacktrace is not impacted by this call and the context is exited.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const store = { id: 2 };
|
||||||
|
* try {
|
||||||
|
* asyncLocalStorage.run(store, () => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object
|
||||||
|
* setTimeout(() => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object
|
||||||
|
* }, 200);
|
||||||
|
* throw new Error();
|
||||||
|
* });
|
||||||
|
* } catch (e) {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns undefined
|
||||||
|
* // The error will be caught here
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
*/
|
||||||
|
run<R>(store: T, callback: () => R): R;
|
||||||
|
run<R, TArgs extends any[]>(store: T, callback: (...args: TArgs) => R, ...args: TArgs): R;
|
||||||
|
/**
|
||||||
|
* Runs a function synchronously outside of a context and returns its
|
||||||
|
* return value. The store is not accessible within the callback function or
|
||||||
|
* the asynchronous operations created within the callback. Any `getStore()` call done within the callback function will always return `undefined`.
|
||||||
|
*
|
||||||
|
* The optional `args` are passed to the callback function.
|
||||||
|
*
|
||||||
|
* If the callback function throws an error, the error is thrown by `exit()` too.
|
||||||
|
* The stacktrace is not impacted by this call and the context is re-entered.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // Within a call to run
|
||||||
|
* try {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object or value
|
||||||
|
* asyncLocalStorage.exit(() => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns undefined
|
||||||
|
* throw new Error();
|
||||||
|
* });
|
||||||
|
* } catch (e) {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object or value
|
||||||
|
* // The error will be caught here
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v13.10.0, v12.17.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
exit<R, TArgs extends any[]>(callback: (...args: TArgs) => R, ...args: TArgs): R;
|
||||||
|
/**
|
||||||
|
* Transitions into the context for the remainder of the current
|
||||||
|
* synchronous execution and then persists the store through any following
|
||||||
|
* asynchronous calls.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const store = { id: 1 };
|
||||||
|
* // Replaces previous store with the given store object
|
||||||
|
* asyncLocalStorage.enterWith(store);
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the store object
|
||||||
|
* someAsyncOperation(() => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This transition will continue for the _entire_ synchronous execution.
|
||||||
|
* This means that if, for example, the context is entered within an event
|
||||||
|
* handler subsequent event handlers will also run within that context unless
|
||||||
|
* specifically bound to another context with an `AsyncResource`. That is why `run()` should be preferred over `enterWith()` unless there are strong reasons
|
||||||
|
* to use the latter method.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const store = { id: 1 };
|
||||||
|
*
|
||||||
|
* emitter.on('my-event', () => {
|
||||||
|
* asyncLocalStorage.enterWith(store);
|
||||||
|
* });
|
||||||
|
* emitter.on('my-event', () => {
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* asyncLocalStorage.getStore(); // Returns undefined
|
||||||
|
* emitter.emit('my-event');
|
||||||
|
* asyncLocalStorage.getStore(); // Returns the same object
|
||||||
|
* ```
|
||||||
|
* @since v13.11.0, v12.17.0
|
||||||
|
* @experimental
|
||||||
|
*/
|
||||||
|
enterWith(store: T): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @since v17.2.0, v16.14.0
|
||||||
|
* @return A map of provider types to the corresponding numeric id.
|
||||||
|
* This map contains all the event types that might be emitted by the `async_hooks.init()` event.
|
||||||
|
*/
|
||||||
|
namespace asyncWrapProviders {
|
||||||
|
const NONE: number;
|
||||||
|
const DIRHANDLE: number;
|
||||||
|
const DNSCHANNEL: number;
|
||||||
|
const ELDHISTOGRAM: number;
|
||||||
|
const FILEHANDLE: number;
|
||||||
|
const FILEHANDLECLOSEREQ: number;
|
||||||
|
const FIXEDSIZEBLOBCOPY: number;
|
||||||
|
const FSEVENTWRAP: number;
|
||||||
|
const FSREQCALLBACK: number;
|
||||||
|
const FSREQPROMISE: number;
|
||||||
|
const GETADDRINFOREQWRAP: number;
|
||||||
|
const GETNAMEINFOREQWRAP: number;
|
||||||
|
const HEAPSNAPSHOT: number;
|
||||||
|
const HTTP2SESSION: number;
|
||||||
|
const HTTP2STREAM: number;
|
||||||
|
const HTTP2PING: number;
|
||||||
|
const HTTP2SETTINGS: number;
|
||||||
|
const HTTPINCOMINGMESSAGE: number;
|
||||||
|
const HTTPCLIENTREQUEST: number;
|
||||||
|
const JSSTREAM: number;
|
||||||
|
const JSUDPWRAP: number;
|
||||||
|
const MESSAGEPORT: number;
|
||||||
|
const PIPECONNECTWRAP: number;
|
||||||
|
const PIPESERVERWRAP: number;
|
||||||
|
const PIPEWRAP: number;
|
||||||
|
const PROCESSWRAP: number;
|
||||||
|
const PROMISE: number;
|
||||||
|
const QUERYWRAP: number;
|
||||||
|
const SHUTDOWNWRAP: number;
|
||||||
|
const SIGNALWRAP: number;
|
||||||
|
const STATWATCHER: number;
|
||||||
|
const STREAMPIPE: number;
|
||||||
|
const TCPCONNECTWRAP: number;
|
||||||
|
const TCPSERVERWRAP: number;
|
||||||
|
const TCPWRAP: number;
|
||||||
|
const TTYWRAP: number;
|
||||||
|
const UDPSENDWRAP: number;
|
||||||
|
const UDPWRAP: number;
|
||||||
|
const SIGINTWATCHDOG: number;
|
||||||
|
const WORKER: number;
|
||||||
|
const WORKERHEAPSNAPSHOT: number;
|
||||||
|
const WRITEWRAP: number;
|
||||||
|
const ZLIB: number;
|
||||||
|
const CHECKPRIMEREQUEST: number;
|
||||||
|
const PBKDF2REQUEST: number;
|
||||||
|
const KEYPAIRGENREQUEST: number;
|
||||||
|
const KEYGENREQUEST: number;
|
||||||
|
const KEYEXPORTREQUEST: number;
|
||||||
|
const CIPHERREQUEST: number;
|
||||||
|
const DERIVEBITSREQUEST: number;
|
||||||
|
const HASHREQUEST: number;
|
||||||
|
const RANDOMBYTESREQUEST: number;
|
||||||
|
const RANDOMPRIMEREQUEST: number;
|
||||||
|
const SCRYPTREQUEST: number;
|
||||||
|
const SIGNREQUEST: number;
|
||||||
|
const TLSWRAP: number;
|
||||||
|
const VERIFYREQUEST: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "node:async_hooks" {
|
||||||
|
export * from "async_hooks";
|
||||||
|
}
|
463
em2rp/node_modules/@types/node/buffer.buffer.d.ts
generated
vendored
Normal file
463
em2rp/node_modules/@types/node/buffer.buffer.d.ts
generated
vendored
Normal file
@ -0,0 +1,463 @@
|
|||||||
|
declare module "buffer" {
|
||||||
|
type ImplicitArrayBuffer<T extends WithImplicitCoercion<ArrayBufferLike>> = T extends
|
||||||
|
{ valueOf(): infer V extends ArrayBufferLike } ? V : T;
|
||||||
|
global {
|
||||||
|
interface BufferConstructor {
|
||||||
|
// see buffer.d.ts for implementation shared with all TypeScript versions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocates a new buffer containing the given {str}.
|
||||||
|
*
|
||||||
|
* @param str String to store in buffer.
|
||||||
|
* @param encoding encoding to use, optional. Default is 'utf8'
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.from(string[, encoding])` instead.
|
||||||
|
*/
|
||||||
|
new(str: string, encoding?: BufferEncoding): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new buffer of {size} octets.
|
||||||
|
*
|
||||||
|
* @param size count of octets to allocate.
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.alloc()` instead (also see `Buffer.allocUnsafe()`).
|
||||||
|
*/
|
||||||
|
new(size: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new buffer containing the given {array} of octets.
|
||||||
|
*
|
||||||
|
* @param array The octets to store.
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.from(array)` instead.
|
||||||
|
*/
|
||||||
|
new(array: ArrayLike<number>): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Produces a Buffer backed by the same allocated memory as
|
||||||
|
* the given {ArrayBuffer}/{SharedArrayBuffer}.
|
||||||
|
*
|
||||||
|
* @param arrayBuffer The ArrayBuffer with which to share memory.
|
||||||
|
* @deprecated since v10.0.0 - Use `Buffer.from(arrayBuffer[, byteOffset[, length]])` instead.
|
||||||
|
*/
|
||||||
|
new<TArrayBuffer extends ArrayBufferLike = ArrayBuffer>(arrayBuffer: TArrayBuffer): Buffer<TArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` using an `array` of bytes in the range `0` – `255`.
|
||||||
|
* Array entries outside that range will be truncated to fit into it.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'.
|
||||||
|
* const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If `array` is an `Array`-like object (that is, one with a `length` property of
|
||||||
|
* type `number`), it is treated as if it is an array, unless it is a `Buffer` or
|
||||||
|
* a `Uint8Array`. This means all other `TypedArray` variants get treated as an
|
||||||
|
* `Array`. To create a `Buffer` from the bytes backing a `TypedArray`, use
|
||||||
|
* `Buffer.copyBytesFrom()`.
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `array` is not an `Array` or another type
|
||||||
|
* appropriate for `Buffer.from()` variants.
|
||||||
|
*
|
||||||
|
* `Buffer.from(array)` and `Buffer.from(string)` may also use the internal
|
||||||
|
* `Buffer` pool like `Buffer.allocUnsafe()` does.
|
||||||
|
* @since v5.10.0
|
||||||
|
*/
|
||||||
|
from(array: WithImplicitCoercion<ArrayLike<number>>): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* This creates a view of the `ArrayBuffer` without copying the underlying
|
||||||
|
* memory. For example, when passed a reference to the `.buffer` property of a
|
||||||
|
* `TypedArray` instance, the newly created `Buffer` will share the same
|
||||||
|
* allocated memory as the `TypedArray`'s underlying `ArrayBuffer`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const arr = new Uint16Array(2);
|
||||||
|
*
|
||||||
|
* arr[0] = 5000;
|
||||||
|
* arr[1] = 4000;
|
||||||
|
*
|
||||||
|
* // Shares memory with `arr`.
|
||||||
|
* const buf = Buffer.from(arr.buffer);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 88 13 a0 0f>
|
||||||
|
*
|
||||||
|
* // Changing the original Uint16Array changes the Buffer also.
|
||||||
|
* arr[1] = 6000;
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 88 13 70 17>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* The optional `byteOffset` and `length` arguments specify a memory range within
|
||||||
|
* the `arrayBuffer` that will be shared by the `Buffer`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const ab = new ArrayBuffer(10);
|
||||||
|
* const buf = Buffer.from(ab, 0, 2);
|
||||||
|
*
|
||||||
|
* console.log(buf.length);
|
||||||
|
* // Prints: 2
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer` or a
|
||||||
|
* `SharedArrayBuffer` or another type appropriate for `Buffer.from()`
|
||||||
|
* variants.
|
||||||
|
*
|
||||||
|
* It is important to remember that a backing `ArrayBuffer` can cover a range
|
||||||
|
* of memory that extends beyond the bounds of a `TypedArray` view. A new
|
||||||
|
* `Buffer` created using the `buffer` property of a `TypedArray` may extend
|
||||||
|
* beyond the range of the `TypedArray`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements
|
||||||
|
* const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements
|
||||||
|
* console.log(arrA.buffer === arrB.buffer); // true
|
||||||
|
*
|
||||||
|
* const buf = Buffer.from(arrB.buffer);
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 63 64 65 66>
|
||||||
|
* ```
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param arrayBuffer An `ArrayBuffer`, `SharedArrayBuffer`, for example the
|
||||||
|
* `.buffer` property of a `TypedArray`.
|
||||||
|
* @param byteOffset Index of first byte to expose. **Default:** `0`.
|
||||||
|
* @param length Number of bytes to expose. **Default:**
|
||||||
|
* `arrayBuffer.byteLength - byteOffset`.
|
||||||
|
*/
|
||||||
|
from<TArrayBuffer extends WithImplicitCoercion<ArrayBufferLike>>(
|
||||||
|
arrayBuffer: TArrayBuffer,
|
||||||
|
byteOffset?: number,
|
||||||
|
length?: number,
|
||||||
|
): Buffer<ImplicitArrayBuffer<TArrayBuffer>>;
|
||||||
|
/**
|
||||||
|
* Creates a new `Buffer` containing `string`. The `encoding` parameter identifies
|
||||||
|
* the character encoding to be used when converting `string` into bytes.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.from('this is a tést');
|
||||||
|
* const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');
|
||||||
|
*
|
||||||
|
* console.log(buf1.toString());
|
||||||
|
* // Prints: this is a tést
|
||||||
|
* console.log(buf2.toString());
|
||||||
|
* // Prints: this is a tést
|
||||||
|
* console.log(buf1.toString('latin1'));
|
||||||
|
* // Prints: this is a tést
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `string` is not a string or another type
|
||||||
|
* appropriate for `Buffer.from()` variants.
|
||||||
|
*
|
||||||
|
* `Buffer.from(string)` may also use the internal `Buffer` pool like
|
||||||
|
* `Buffer.allocUnsafe()` does.
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param string A string to encode.
|
||||||
|
* @param encoding The encoding of `string`. **Default:** `'utf8'`.
|
||||||
|
*/
|
||||||
|
from(string: WithImplicitCoercion<string>, encoding?: BufferEncoding): Buffer<ArrayBuffer>;
|
||||||
|
from(arrayOrString: WithImplicitCoercion<ArrayLike<number> | string>): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Creates a new Buffer using the passed {data}
|
||||||
|
* @param values to create a new Buffer
|
||||||
|
*/
|
||||||
|
of(...items: number[]): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Returns a new `Buffer` which is the result of concatenating all the `Buffer` instances in the `list` together.
|
||||||
|
*
|
||||||
|
* If the list has no items, or if the `totalLength` is 0, then a new zero-length `Buffer` is returned.
|
||||||
|
*
|
||||||
|
* If `totalLength` is not provided, it is calculated from the `Buffer` instances
|
||||||
|
* in `list` by adding their lengths.
|
||||||
|
*
|
||||||
|
* If `totalLength` is provided, it is coerced to an unsigned integer. If the
|
||||||
|
* combined length of the `Buffer`s in `list` exceeds `totalLength`, the result is
|
||||||
|
* truncated to `totalLength`. If the combined length of the `Buffer`s in `list` is
|
||||||
|
* less than `totalLength`, the remaining space is filled with zeros.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Create a single `Buffer` from a list of three `Buffer` instances.
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.alloc(10);
|
||||||
|
* const buf2 = Buffer.alloc(14);
|
||||||
|
* const buf3 = Buffer.alloc(18);
|
||||||
|
* const totalLength = buf1.length + buf2.length + buf3.length;
|
||||||
|
*
|
||||||
|
* console.log(totalLength);
|
||||||
|
* // Prints: 42
|
||||||
|
*
|
||||||
|
* const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);
|
||||||
|
*
|
||||||
|
* console.log(bufA);
|
||||||
|
* // Prints: <Buffer 00 00 00 00 ...>
|
||||||
|
* console.log(bufA.length);
|
||||||
|
* // Prints: 42
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* `Buffer.concat()` may also use the internal `Buffer` pool like `Buffer.allocUnsafe()` does.
|
||||||
|
* @since v0.7.11
|
||||||
|
* @param list List of `Buffer` or {@link Uint8Array} instances to concatenate.
|
||||||
|
* @param totalLength Total length of the `Buffer` instances in `list` when concatenated.
|
||||||
|
*/
|
||||||
|
concat(list: readonly Uint8Array[], totalLength?: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Copies the underlying memory of `view` into a new `Buffer`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const u16 = new Uint16Array([0, 0xffff]);
|
||||||
|
* const buf = Buffer.copyBytesFrom(u16, 1, 1);
|
||||||
|
* u16[1] = 0;
|
||||||
|
* console.log(buf.length); // 2
|
||||||
|
* console.log(buf[0]); // 255
|
||||||
|
* console.log(buf[1]); // 255
|
||||||
|
* ```
|
||||||
|
* @since v19.8.0
|
||||||
|
* @param view The {TypedArray} to copy.
|
||||||
|
* @param [offset=0] The starting offset within `view`.
|
||||||
|
* @param [length=view.length - offset] The number of elements from `view` to copy.
|
||||||
|
*/
|
||||||
|
copyBytesFrom(view: NodeJS.TypedArray, offset?: number, length?: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the`Buffer` will be zero-filled.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.alloc(5);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 00 00 00 00 00>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown.
|
||||||
|
*
|
||||||
|
* If `fill` is specified, the allocated `Buffer` will be initialized by calling `buf.fill(fill)`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.alloc(5, 'a');
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 61 61 61 61 61>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If both `fill` and `encoding` are specified, the allocated `Buffer` will be
|
||||||
|
* initialized by calling `buf.fill(fill, encoding)`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Calling `Buffer.alloc()` can be measurably slower than the alternative `Buffer.allocUnsafe()` but ensures that the newly created `Buffer` instance
|
||||||
|
* contents will never contain sensitive data from previous allocations, including
|
||||||
|
* data that might not have been allocated for `Buffer`s.
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `size` is not a number.
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param size The desired length of the new `Buffer`.
|
||||||
|
* @param [fill=0] A value to pre-fill the new `Buffer` with.
|
||||||
|
* @param [encoding='utf8'] If `fill` is a string, this is its encoding.
|
||||||
|
*/
|
||||||
|
alloc(size: number, fill?: string | Uint8Array | number, encoding?: BufferEncoding): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown.
|
||||||
|
*
|
||||||
|
* The underlying memory for `Buffer` instances created in this way is _not_
|
||||||
|
* _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `Buffer.alloc()` instead to initialize`Buffer` instances with zeroes.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.allocUnsafe(10);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32>
|
||||||
|
*
|
||||||
|
* buf.fill(0);
|
||||||
|
*
|
||||||
|
* console.log(buf);
|
||||||
|
* // Prints: <Buffer 00 00 00 00 00 00 00 00 00 00>
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `size` is not a number.
|
||||||
|
*
|
||||||
|
* The `Buffer` module pre-allocates an internal `Buffer` instance of
|
||||||
|
* size `Buffer.poolSize` that is used as a pool for the fast allocation of new `Buffer` instances created using `Buffer.allocUnsafe()`, `Buffer.from(array)`,
|
||||||
|
* and `Buffer.concat()` only when `size` is less than `Buffer.poolSize >>> 1` (floor of `Buffer.poolSize` divided by two).
|
||||||
|
*
|
||||||
|
* Use of this pre-allocated internal memory pool is a key difference between
|
||||||
|
* calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`.
|
||||||
|
* Specifically, `Buffer.alloc(size, fill)` will _never_ use the internal `Buffer`pool, while `Buffer.allocUnsafe(size).fill(fill)`_will_ use the internal`Buffer` pool if `size` is less
|
||||||
|
* than or equal to half `Buffer.poolSize`. The
|
||||||
|
* difference is subtle but can be important when an application requires the
|
||||||
|
* additional performance that `Buffer.allocUnsafe()` provides.
|
||||||
|
* @since v5.10.0
|
||||||
|
* @param size The desired length of the new `Buffer`.
|
||||||
|
*/
|
||||||
|
allocUnsafe(size: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Allocates a new `Buffer` of `size` bytes. If `size` is larger than {@link constants.MAX_LENGTH} or smaller than 0, `ERR_OUT_OF_RANGE` is thrown. A zero-length `Buffer` is created if
|
||||||
|
* `size` is 0.
|
||||||
|
*
|
||||||
|
* The underlying memory for `Buffer` instances created in this way is _not_
|
||||||
|
* _initialized_. The contents of the newly created `Buffer` are unknown and _may contain sensitive data_. Use `buf.fill(0)` to initialize
|
||||||
|
* such `Buffer` instances with zeroes.
|
||||||
|
*
|
||||||
|
* When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances,
|
||||||
|
* allocations under 4 KiB are sliced from a single pre-allocated `Buffer`. This
|
||||||
|
* allows applications to avoid the garbage collection overhead of creating many
|
||||||
|
* individually allocated `Buffer` instances. This approach improves both
|
||||||
|
* performance and memory usage by eliminating the need to track and clean up as
|
||||||
|
* many individual `ArrayBuffer` objects.
|
||||||
|
*
|
||||||
|
* However, in the case where a developer may need to retain a small chunk of
|
||||||
|
* memory from a pool for an indeterminate amount of time, it may be appropriate
|
||||||
|
* to create an un-pooled `Buffer` instance using `Buffer.allocUnsafeSlow()` and
|
||||||
|
* then copying out the relevant bits.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Need to keep around a few small chunks of memory.
|
||||||
|
* const store = [];
|
||||||
|
*
|
||||||
|
* socket.on('readable', () => {
|
||||||
|
* let data;
|
||||||
|
* while (null !== (data = readable.read())) {
|
||||||
|
* // Allocate for retained data.
|
||||||
|
* const sb = Buffer.allocUnsafeSlow(10);
|
||||||
|
*
|
||||||
|
* // Copy the data into the new allocation.
|
||||||
|
* data.copy(sb, 0, 0, 10);
|
||||||
|
*
|
||||||
|
* store.push(sb);
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* A `TypeError` will be thrown if `size` is not a number.
|
||||||
|
* @since v5.12.0
|
||||||
|
* @param size The desired length of the new `Buffer`.
|
||||||
|
*/
|
||||||
|
allocUnsafeSlow(size: number): Buffer<ArrayBuffer>;
|
||||||
|
}
|
||||||
|
interface Buffer<TArrayBuffer extends ArrayBufferLike = ArrayBufferLike> extends Uint8Array<TArrayBuffer> {
|
||||||
|
// see buffer.d.ts for implementation shared with all TypeScript versions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new `Buffer` that references the same memory as the original, but
|
||||||
|
* offset and cropped by the `start` and `end` indices.
|
||||||
|
*
|
||||||
|
* This method is not compatible with the `Uint8Array.prototype.slice()`,
|
||||||
|
* which is a superclass of `Buffer`. To copy the slice, use`Uint8Array.prototype.slice()`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.from('buffer');
|
||||||
|
*
|
||||||
|
* const copiedBuf = Uint8Array.prototype.slice.call(buf);
|
||||||
|
* copiedBuf[0]++;
|
||||||
|
* console.log(copiedBuf.toString());
|
||||||
|
* // Prints: cuffer
|
||||||
|
*
|
||||||
|
* console.log(buf.toString());
|
||||||
|
* // Prints: buffer
|
||||||
|
*
|
||||||
|
* // With buf.slice(), the original buffer is modified.
|
||||||
|
* const notReallyCopiedBuf = buf.slice();
|
||||||
|
* notReallyCopiedBuf[0]++;
|
||||||
|
* console.log(notReallyCopiedBuf.toString());
|
||||||
|
* // Prints: cuffer
|
||||||
|
* console.log(buf.toString());
|
||||||
|
* // Also prints: cuffer (!)
|
||||||
|
* ```
|
||||||
|
* @since v0.3.0
|
||||||
|
* @deprecated Use `subarray` instead.
|
||||||
|
* @param [start=0] Where the new `Buffer` will start.
|
||||||
|
* @param [end=buf.length] Where the new `Buffer` will end (not inclusive).
|
||||||
|
*/
|
||||||
|
slice(start?: number, end?: number): Buffer<ArrayBuffer>;
|
||||||
|
/**
|
||||||
|
* Returns a new `Buffer` that references the same memory as the original, but
|
||||||
|
* offset and cropped by the `start` and `end` indices.
|
||||||
|
*
|
||||||
|
* Specifying `end` greater than `buf.length` will return the same result as
|
||||||
|
* that of `end` equal to `buf.length`.
|
||||||
|
*
|
||||||
|
* This method is inherited from [`TypedArray.prototype.subarray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/subarray).
|
||||||
|
*
|
||||||
|
* Modifying the new `Buffer` slice will modify the memory in the original `Buffer`because the allocated memory of the two objects overlap.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* // Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte
|
||||||
|
* // from the original `Buffer`.
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.allocUnsafe(26);
|
||||||
|
*
|
||||||
|
* for (let i = 0; i < 26; i++) {
|
||||||
|
* // 97 is the decimal ASCII value for 'a'.
|
||||||
|
* buf1[i] = i + 97;
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* const buf2 = buf1.subarray(0, 3);
|
||||||
|
*
|
||||||
|
* console.log(buf2.toString('ascii', 0, buf2.length));
|
||||||
|
* // Prints: abc
|
||||||
|
*
|
||||||
|
* buf1[0] = 33;
|
||||||
|
*
|
||||||
|
* console.log(buf2.toString('ascii', 0, buf2.length));
|
||||||
|
* // Prints: !bc
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Specifying negative indexes causes the slice to be generated relative to the
|
||||||
|
* end of `buf` rather than the beginning.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf = Buffer.from('buffer');
|
||||||
|
*
|
||||||
|
* console.log(buf.subarray(-6, -1).toString());
|
||||||
|
* // Prints: buffe
|
||||||
|
* // (Equivalent to buf.subarray(0, 5).)
|
||||||
|
*
|
||||||
|
* console.log(buf.subarray(-6, -2).toString());
|
||||||
|
* // Prints: buff
|
||||||
|
* // (Equivalent to buf.subarray(0, 4).)
|
||||||
|
*
|
||||||
|
* console.log(buf.subarray(-5, -2).toString());
|
||||||
|
* // Prints: uff
|
||||||
|
* // (Equivalent to buf.subarray(1, 4).)
|
||||||
|
* ```
|
||||||
|
* @since v3.0.0
|
||||||
|
* @param [start=0] Where the new `Buffer` will start.
|
||||||
|
* @param [end=buf.length] Where the new `Buffer` will end (not inclusive).
|
||||||
|
*/
|
||||||
|
subarray(start?: number, end?: number): Buffer<TArrayBuffer>;
|
||||||
|
}
|
||||||
|
type NonSharedBuffer = Buffer<ArrayBuffer>;
|
||||||
|
type AllowSharedBuffer = Buffer<ArrayBufferLike>;
|
||||||
|
}
|
||||||
|
/** @deprecated Use `Buffer.allocUnsafeSlow()` instead. */
|
||||||
|
var SlowBuffer: {
|
||||||
|
/** @deprecated Use `Buffer.allocUnsafeSlow()` instead. */
|
||||||
|
new(size: number): Buffer<ArrayBuffer>;
|
||||||
|
prototype: Buffer;
|
||||||
|
};
|
||||||
|
}
|
1926
em2rp/node_modules/@types/node/buffer.d.ts
generated
vendored
Normal file
1926
em2rp/node_modules/@types/node/buffer.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1549
em2rp/node_modules/@types/node/child_process.d.ts
generated
vendored
Normal file
1549
em2rp/node_modules/@types/node/child_process.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
579
em2rp/node_modules/@types/node/cluster.d.ts
generated
vendored
Normal file
579
em2rp/node_modules/@types/node/cluster.d.ts
generated
vendored
Normal file
@ -0,0 +1,579 @@
|
|||||||
|
/**
|
||||||
|
* Clusters of Node.js processes can be used to run multiple instances of Node.js
|
||||||
|
* that can distribute workloads among their application threads. When process isolation
|
||||||
|
* is not needed, use the [`worker_threads`](https://nodejs.org/docs/latest-v22.x/api/worker_threads.html)
|
||||||
|
* module instead, which allows running multiple application threads within a single Node.js instance.
|
||||||
|
*
|
||||||
|
* The cluster module allows easy creation of child processes that all share
|
||||||
|
* server ports.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
* import http from 'node:http';
|
||||||
|
* import { availableParallelism } from 'node:os';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const numCPUs = availableParallelism();
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* console.log(`Primary ${process.pid} is running`);
|
||||||
|
*
|
||||||
|
* // Fork workers.
|
||||||
|
* for (let i = 0; i < numCPUs; i++) {
|
||||||
|
* cluster.fork();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* cluster.on('exit', (worker, code, signal) => {
|
||||||
|
* console.log(`worker ${worker.process.pid} died`);
|
||||||
|
* });
|
||||||
|
* } else {
|
||||||
|
* // Workers can share any TCP connection
|
||||||
|
* // In this case it is an HTTP server
|
||||||
|
* http.createServer((req, res) => {
|
||||||
|
* res.writeHead(200);
|
||||||
|
* res.end('hello world\n');
|
||||||
|
* }).listen(8000);
|
||||||
|
*
|
||||||
|
* console.log(`Worker ${process.pid} started`);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Running Node.js will now share port 8000 between the workers:
|
||||||
|
*
|
||||||
|
* ```console
|
||||||
|
* $ node server.js
|
||||||
|
* Primary 3596 is running
|
||||||
|
* Worker 4324 started
|
||||||
|
* Worker 4520 started
|
||||||
|
* Worker 6056 started
|
||||||
|
* Worker 5644 started
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* On Windows, it is not yet possible to set up a named pipe server in a worker.
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v22.x/lib/cluster.js)
|
||||||
|
*/
|
||||||
|
declare module "cluster" {
|
||||||
|
import * as child from "node:child_process";
|
||||||
|
import EventEmitter = require("node:events");
|
||||||
|
import * as net from "node:net";
|
||||||
|
type SerializationType = "json" | "advanced";
|
||||||
|
export interface ClusterSettings {
|
||||||
|
/**
|
||||||
|
* List of string arguments passed to the Node.js executable.
|
||||||
|
* @default process.execArgv
|
||||||
|
*/
|
||||||
|
execArgv?: string[] | undefined;
|
||||||
|
/**
|
||||||
|
* File path to worker file.
|
||||||
|
* @default process.argv[1]
|
||||||
|
*/
|
||||||
|
exec?: string | undefined;
|
||||||
|
/**
|
||||||
|
* String arguments passed to worker.
|
||||||
|
* @default process.argv.slice(2)
|
||||||
|
*/
|
||||||
|
args?: string[] | undefined;
|
||||||
|
/**
|
||||||
|
* Whether or not to send output to parent's stdio.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
silent?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Configures the stdio of forked processes. Because the cluster module relies on IPC to function, this configuration must
|
||||||
|
* contain an `'ipc'` entry. When this option is provided, it overrides `silent`. See [`child_prcess.spawn()`](https://nodejs.org/docs/latest-v22.x/api/child_process.html#child_processspawncommand-args-options)'s
|
||||||
|
* [`stdio`](https://nodejs.org/docs/latest-v22.x/api/child_process.html#optionsstdio).
|
||||||
|
*/
|
||||||
|
stdio?: any[] | undefined;
|
||||||
|
/**
|
||||||
|
* Sets the user identity of the process. (See [`setuid(2)`](https://man7.org/linux/man-pages/man2/setuid.2.html).)
|
||||||
|
*/
|
||||||
|
uid?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Sets the group identity of the process. (See [`setgid(2)`](https://man7.org/linux/man-pages/man2/setgid.2.html).)
|
||||||
|
*/
|
||||||
|
gid?: number | undefined;
|
||||||
|
/**
|
||||||
|
* Sets inspector port of worker. This can be a number, or a function that takes no arguments and returns a number.
|
||||||
|
* By default each worker gets its own port, incremented from the primary's `process.debugPort`.
|
||||||
|
*/
|
||||||
|
inspectPort?: number | (() => number) | undefined;
|
||||||
|
/**
|
||||||
|
* Specify the kind of serialization used for sending messages between processes. Possible values are `'json'` and `'advanced'`.
|
||||||
|
* See [Advanced serialization for `child_process`](https://nodejs.org/docs/latest-v22.x/api/child_process.html#advanced-serialization) for more details.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
serialization?: SerializationType | undefined;
|
||||||
|
/**
|
||||||
|
* Current working directory of the worker process.
|
||||||
|
* @default undefined (inherits from parent process)
|
||||||
|
*/
|
||||||
|
cwd?: string | undefined;
|
||||||
|
/**
|
||||||
|
* Hide the forked processes console window that would normally be created on Windows systems.
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
windowsHide?: boolean | undefined;
|
||||||
|
}
|
||||||
|
export interface Address {
|
||||||
|
address: string;
|
||||||
|
port: number;
|
||||||
|
/**
|
||||||
|
* The `addressType` is one of:
|
||||||
|
*
|
||||||
|
* * `4` (TCPv4)
|
||||||
|
* * `6` (TCPv6)
|
||||||
|
* * `-1` (Unix domain socket)
|
||||||
|
* * `'udp4'` or `'udp6'` (UDPv4 or UDPv6)
|
||||||
|
*/
|
||||||
|
addressType: 4 | 6 | -1 | "udp4" | "udp6";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* A `Worker` object contains all public information and method about a worker.
|
||||||
|
* In the primary it can be obtained using `cluster.workers`. In a worker
|
||||||
|
* it can be obtained using `cluster.worker`.
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
export class Worker extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Each new worker is given its own unique id, this id is stored in the `id`.
|
||||||
|
*
|
||||||
|
* While a worker is alive, this is the key that indexes it in `cluster.workers`.
|
||||||
|
* @since v0.8.0
|
||||||
|
*/
|
||||||
|
id: number;
|
||||||
|
/**
|
||||||
|
* All workers are created using [`child_process.fork()`](https://nodejs.org/docs/latest-v22.x/api/child_process.html#child_processforkmodulepath-args-options), the returned object
|
||||||
|
* from this function is stored as `.process`. In a worker, the global `process` is stored.
|
||||||
|
*
|
||||||
|
* See: [Child Process module](https://nodejs.org/docs/latest-v22.x/api/child_process.html#child_processforkmodulepath-args-options).
|
||||||
|
*
|
||||||
|
* Workers will call `process.exit(0)` if the `'disconnect'` event occurs
|
||||||
|
* on `process` and `.exitedAfterDisconnect` is not `true`. This protects against
|
||||||
|
* accidental disconnection.
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
process: child.ChildProcess;
|
||||||
|
/**
|
||||||
|
* Send a message to a worker or primary, optionally with a handle.
|
||||||
|
*
|
||||||
|
* In the primary, this sends a message to a specific worker. It is identical to [`ChildProcess.send()`](https://nodejs.org/docs/latest-v22.x/api/child_process.html#subprocesssendmessage-sendhandle-options-callback).
|
||||||
|
*
|
||||||
|
* In a worker, this sends a message to the primary. It is identical to `process.send()`.
|
||||||
|
*
|
||||||
|
* This example will echo back all messages from the primary:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* const worker = cluster.fork();
|
||||||
|
* worker.send('hi there');
|
||||||
|
*
|
||||||
|
* } else if (cluster.isWorker) {
|
||||||
|
* process.on('message', (msg) => {
|
||||||
|
* process.send(msg);
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.0
|
||||||
|
* @param options The `options` argument, if present, is an object used to parameterize the sending of certain types of handles.
|
||||||
|
*/
|
||||||
|
send(message: child.Serializable, callback?: (error: Error | null) => void): boolean;
|
||||||
|
send(
|
||||||
|
message: child.Serializable,
|
||||||
|
sendHandle: child.SendHandle,
|
||||||
|
callback?: (error: Error | null) => void,
|
||||||
|
): boolean;
|
||||||
|
send(
|
||||||
|
message: child.Serializable,
|
||||||
|
sendHandle: child.SendHandle,
|
||||||
|
options?: child.MessageOptions,
|
||||||
|
callback?: (error: Error | null) => void,
|
||||||
|
): boolean;
|
||||||
|
/**
|
||||||
|
* This function will kill the worker. In the primary worker, it does this by
|
||||||
|
* disconnecting the `worker.process`, and once disconnected, killing with `signal`. In the worker, it does it by killing the process with `signal`.
|
||||||
|
*
|
||||||
|
* The `kill()` function kills the worker process without waiting for a graceful
|
||||||
|
* disconnect, it has the same behavior as `worker.process.kill()`.
|
||||||
|
*
|
||||||
|
* This method is aliased as `worker.destroy()` for backwards compatibility.
|
||||||
|
*
|
||||||
|
* In a worker, `process.kill()` exists, but it is not this function;
|
||||||
|
* it is [`kill()`](https://nodejs.org/docs/latest-v22.x/api/process.html#processkillpid-signal).
|
||||||
|
* @since v0.9.12
|
||||||
|
* @param [signal='SIGTERM'] Name of the kill signal to send to the worker process.
|
||||||
|
*/
|
||||||
|
kill(signal?: string): void;
|
||||||
|
destroy(signal?: string): void;
|
||||||
|
/**
|
||||||
|
* In a worker, this function will close all servers, wait for the `'close'` event
|
||||||
|
* on those servers, and then disconnect the IPC channel.
|
||||||
|
*
|
||||||
|
* In the primary, an internal message is sent to the worker causing it to call `.disconnect()` on itself.
|
||||||
|
*
|
||||||
|
* Causes `.exitedAfterDisconnect` to be set.
|
||||||
|
*
|
||||||
|
* After a server is closed, it will no longer accept new connections,
|
||||||
|
* but connections may be accepted by any other listening worker. Existing
|
||||||
|
* connections will be allowed to close as usual. When no more connections exist,
|
||||||
|
* see `server.close()`, the IPC channel to the worker will close allowing it
|
||||||
|
* to die gracefully.
|
||||||
|
*
|
||||||
|
* The above applies _only_ to server connections, client connections are not
|
||||||
|
* automatically closed by workers, and disconnect does not wait for them to close
|
||||||
|
* before exiting.
|
||||||
|
*
|
||||||
|
* In a worker, `process.disconnect` exists, but it is not this function;
|
||||||
|
* it is `disconnect()`.
|
||||||
|
*
|
||||||
|
* Because long living server connections may block workers from disconnecting, it
|
||||||
|
* may be useful to send a message, so application specific actions may be taken to
|
||||||
|
* close them. It also may be useful to implement a timeout, killing a worker if
|
||||||
|
* the `'disconnect'` event has not been emitted after some time.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import net from 'node:net';
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* const worker = cluster.fork();
|
||||||
|
* let timeout;
|
||||||
|
*
|
||||||
|
* worker.on('listening', (address) => {
|
||||||
|
* worker.send('shutdown');
|
||||||
|
* worker.disconnect();
|
||||||
|
* timeout = setTimeout(() => {
|
||||||
|
* worker.kill();
|
||||||
|
* }, 2000);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* worker.on('disconnect', () => {
|
||||||
|
* clearTimeout(timeout);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* } else if (cluster.isWorker) {
|
||||||
|
* const server = net.createServer((socket) => {
|
||||||
|
* // Connections never end
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.listen(8000);
|
||||||
|
*
|
||||||
|
* process.on('message', (msg) => {
|
||||||
|
* if (msg === 'shutdown') {
|
||||||
|
* // Initiate graceful close of any connections to server
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.7
|
||||||
|
* @return A reference to `worker`.
|
||||||
|
*/
|
||||||
|
disconnect(): this;
|
||||||
|
/**
|
||||||
|
* This function returns `true` if the worker is connected to its primary via its
|
||||||
|
* IPC channel, `false` otherwise. A worker is connected to its primary after it
|
||||||
|
* has been created. It is disconnected after the `'disconnect'` event is emitted.
|
||||||
|
* @since v0.11.14
|
||||||
|
*/
|
||||||
|
isConnected(): boolean;
|
||||||
|
/**
|
||||||
|
* This function returns `true` if the worker's process has terminated (either
|
||||||
|
* because of exiting or being signaled). Otherwise, it returns `false`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
* import http from 'node:http';
|
||||||
|
* import { availableParallelism } from 'node:os';
|
||||||
|
* import process from 'node:process';
|
||||||
|
*
|
||||||
|
* const numCPUs = availableParallelism();
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* console.log(`Primary ${process.pid} is running`);
|
||||||
|
*
|
||||||
|
* // Fork workers.
|
||||||
|
* for (let i = 0; i < numCPUs; i++) {
|
||||||
|
* cluster.fork();
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* cluster.on('fork', (worker) => {
|
||||||
|
* console.log('worker is dead:', worker.isDead());
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* cluster.on('exit', (worker, code, signal) => {
|
||||||
|
* console.log('worker is dead:', worker.isDead());
|
||||||
|
* });
|
||||||
|
* } else {
|
||||||
|
* // Workers can share any TCP connection. In this case, it is an HTTP server.
|
||||||
|
* http.createServer((req, res) => {
|
||||||
|
* res.writeHead(200);
|
||||||
|
* res.end(`Current process\n ${process.pid}`);
|
||||||
|
* process.kill(process.pid);
|
||||||
|
* }).listen(8000);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.11.14
|
||||||
|
*/
|
||||||
|
isDead(): boolean;
|
||||||
|
/**
|
||||||
|
* This property is `true` if the worker exited due to `.disconnect()`.
|
||||||
|
* If the worker exited any other way, it is `false`. If the
|
||||||
|
* worker has not exited, it is `undefined`.
|
||||||
|
*
|
||||||
|
* The boolean `worker.exitedAfterDisconnect` allows distinguishing between
|
||||||
|
* voluntary and accidental exit, the primary may choose not to respawn a worker
|
||||||
|
* based on this value.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* cluster.on('exit', (worker, code, signal) => {
|
||||||
|
* if (worker.exitedAfterDisconnect === true) {
|
||||||
|
* console.log('Oh, it was just voluntary – no need to worry');
|
||||||
|
* }
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* // kill worker
|
||||||
|
* worker.kill();
|
||||||
|
* ```
|
||||||
|
* @since v6.0.0
|
||||||
|
*/
|
||||||
|
exitedAfterDisconnect: boolean;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. disconnect
|
||||||
|
* 2. error
|
||||||
|
* 3. exit
|
||||||
|
* 4. listening
|
||||||
|
* 5. message
|
||||||
|
* 6. online
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "disconnect", listener: () => void): this;
|
||||||
|
addListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
addListener(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
addListener(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
addListener(event: "online", listener: () => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "disconnect"): boolean;
|
||||||
|
emit(event: "error", error: Error): boolean;
|
||||||
|
emit(event: "exit", code: number, signal: string): boolean;
|
||||||
|
emit(event: "listening", address: Address): boolean;
|
||||||
|
emit(event: "message", message: any, handle: net.Socket | net.Server): boolean;
|
||||||
|
emit(event: "online"): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "disconnect", listener: () => void): this;
|
||||||
|
on(event: "error", listener: (error: Error) => void): this;
|
||||||
|
on(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
on(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
on(event: "online", listener: () => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "disconnect", listener: () => void): this;
|
||||||
|
once(event: "error", listener: (error: Error) => void): this;
|
||||||
|
once(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
once(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
once(event: "online", listener: () => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "disconnect", listener: () => void): this;
|
||||||
|
prependListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
prependListener(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
prependListener(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependListener(event: "online", listener: () => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "disconnect", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "error", listener: (error: Error) => void): this;
|
||||||
|
prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: (address: Address) => void): this;
|
||||||
|
prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependOnceListener(event: "online", listener: () => void): this;
|
||||||
|
}
|
||||||
|
export interface Cluster extends EventEmitter {
|
||||||
|
disconnect(callback?: () => void): void;
|
||||||
|
/**
|
||||||
|
* Spawn a new worker process.
|
||||||
|
*
|
||||||
|
* This can only be called from the primary process.
|
||||||
|
* @param env Key/value pairs to add to worker process environment.
|
||||||
|
* @since v0.6.0
|
||||||
|
*/
|
||||||
|
fork(env?: any): Worker;
|
||||||
|
/** @deprecated since v16.0.0 - use isPrimary. */
|
||||||
|
readonly isMaster: boolean;
|
||||||
|
/**
|
||||||
|
* True if the process is a primary. This is determined by the `process.env.NODE_UNIQUE_ID`. If `process.env.NODE_UNIQUE_ID`
|
||||||
|
* is undefined, then `isPrimary` is `true`.
|
||||||
|
* @since v16.0.0
|
||||||
|
*/
|
||||||
|
readonly isPrimary: boolean;
|
||||||
|
/**
|
||||||
|
* True if the process is not a primary (it is the negation of `cluster.isPrimary`).
|
||||||
|
* @since v0.6.0
|
||||||
|
*/
|
||||||
|
readonly isWorker: boolean;
|
||||||
|
/**
|
||||||
|
* The scheduling policy, either `cluster.SCHED_RR` for round-robin or `cluster.SCHED_NONE` to leave it to the operating system. This is a
|
||||||
|
* global setting and effectively frozen once either the first worker is spawned, or [`.setupPrimary()`](https://nodejs.org/docs/latest-v22.x/api/cluster.html#clustersetupprimarysettings)
|
||||||
|
* is called, whichever comes first.
|
||||||
|
*
|
||||||
|
* `SCHED_RR` is the default on all operating systems except Windows. Windows will change to `SCHED_RR` once libuv is able to effectively distribute
|
||||||
|
* IOCP handles without incurring a large performance hit.
|
||||||
|
*
|
||||||
|
* `cluster.schedulingPolicy` can also be set through the `NODE_CLUSTER_SCHED_POLICY` environment variable. Valid values are `'rr'` and `'none'`.
|
||||||
|
* @since v0.11.2
|
||||||
|
*/
|
||||||
|
schedulingPolicy: number;
|
||||||
|
/**
|
||||||
|
* After calling [`.setupPrimary()`](https://nodejs.org/docs/latest-v22.x/api/cluster.html#clustersetupprimarysettings)
|
||||||
|
* (or [`.fork()`](https://nodejs.org/docs/latest-v22.x/api/cluster.html#clusterforkenv)) this settings object will contain
|
||||||
|
* the settings, including the default values.
|
||||||
|
*
|
||||||
|
* This object is not intended to be changed or set manually.
|
||||||
|
* @since v0.7.1
|
||||||
|
*/
|
||||||
|
readonly settings: ClusterSettings;
|
||||||
|
/** @deprecated since v16.0.0 - use [`.setupPrimary()`](https://nodejs.org/docs/latest-v22.x/api/cluster.html#clustersetupprimarysettings) instead. */
|
||||||
|
setupMaster(settings?: ClusterSettings): void;
|
||||||
|
/**
|
||||||
|
* `setupPrimary` is used to change the default 'fork' behavior. Once called, the settings will be present in `cluster.settings`.
|
||||||
|
*
|
||||||
|
* Any settings changes only affect future calls to [`.fork()`](https://nodejs.org/docs/latest-v22.x/api/cluster.html#clusterforkenv)
|
||||||
|
* and have no effect on workers that are already running.
|
||||||
|
*
|
||||||
|
* The only attribute of a worker that cannot be set via `.setupPrimary()` is the `env` passed to
|
||||||
|
* [`.fork()`](https://nodejs.org/docs/latest-v22.x/api/cluster.html#clusterforkenv).
|
||||||
|
*
|
||||||
|
* The defaults above apply to the first call only; the defaults for later calls are the current values at the time of
|
||||||
|
* `cluster.setupPrimary()` is called.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
*
|
||||||
|
* cluster.setupPrimary({
|
||||||
|
* exec: 'worker.js',
|
||||||
|
* args: ['--use', 'https'],
|
||||||
|
* silent: true,
|
||||||
|
* });
|
||||||
|
* cluster.fork(); // https worker
|
||||||
|
* cluster.setupPrimary({
|
||||||
|
* exec: 'worker.js',
|
||||||
|
* args: ['--use', 'http'],
|
||||||
|
* });
|
||||||
|
* cluster.fork(); // http worker
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* This can only be called from the primary process.
|
||||||
|
* @since v16.0.0
|
||||||
|
*/
|
||||||
|
setupPrimary(settings?: ClusterSettings): void;
|
||||||
|
/**
|
||||||
|
* A reference to the current worker object. Not available in the primary process.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* console.log('I am primary');
|
||||||
|
* cluster.fork();
|
||||||
|
* cluster.fork();
|
||||||
|
* } else if (cluster.isWorker) {
|
||||||
|
* console.log(`I am worker #${cluster.worker.id}`);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
readonly worker?: Worker | undefined;
|
||||||
|
/**
|
||||||
|
* A hash that stores the active worker objects, keyed by `id` field. This makes it easy to loop through all the workers. It is only available in the primary process.
|
||||||
|
*
|
||||||
|
* A worker is removed from `cluster.workers` after the worker has disconnected _and_ exited. The order between these two events cannot be determined in advance. However, it
|
||||||
|
* is guaranteed that the removal from the `cluster.workers` list happens before the last `'disconnect'` or `'exit'` event is emitted.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
*
|
||||||
|
* for (const worker of Object.values(cluster.workers)) {
|
||||||
|
* worker.send('big announcement to all workers');
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.7.0
|
||||||
|
*/
|
||||||
|
readonly workers?: NodeJS.Dict<Worker> | undefined;
|
||||||
|
readonly SCHED_NONE: number;
|
||||||
|
readonly SCHED_RR: number;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. disconnect
|
||||||
|
* 2. exit
|
||||||
|
* 3. fork
|
||||||
|
* 4. listening
|
||||||
|
* 5. message
|
||||||
|
* 6. online
|
||||||
|
* 7. setup
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
addListener(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
addListener(
|
||||||
|
event: "message",
|
||||||
|
listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void,
|
||||||
|
): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
addListener(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
addListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "disconnect", worker: Worker): boolean;
|
||||||
|
emit(event: "exit", worker: Worker, code: number, signal: string): boolean;
|
||||||
|
emit(event: "fork", worker: Worker): boolean;
|
||||||
|
emit(event: "listening", worker: Worker, address: Address): boolean;
|
||||||
|
emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean;
|
||||||
|
emit(event: "online", worker: Worker): boolean;
|
||||||
|
emit(event: "setup", settings: ClusterSettings): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
on(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
on(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
on(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
on(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
once(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
once(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
once(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
once(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
prependListener(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
// the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependListener(
|
||||||
|
event: "message",
|
||||||
|
listener: (worker: Worker, message: any, handle?: net.Socket | net.Server) => void,
|
||||||
|
): this;
|
||||||
|
prependListener(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
prependListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this;
|
||||||
|
prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
|
||||||
|
prependOnceListener(event: "fork", listener: (worker: Worker) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
|
||||||
|
// the handle is a net.Socket or net.Server object, or undefined.
|
||||||
|
prependOnceListener(
|
||||||
|
event: "message",
|
||||||
|
listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void,
|
||||||
|
): this;
|
||||||
|
prependOnceListener(event: "online", listener: (worker: Worker) => void): this;
|
||||||
|
prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
|
||||||
|
}
|
||||||
|
const cluster: Cluster;
|
||||||
|
export default cluster;
|
||||||
|
}
|
||||||
|
declare module "node:cluster" {
|
||||||
|
export * from "cluster";
|
||||||
|
export { default as default } from "cluster";
|
||||||
|
}
|
16
em2rp/node_modules/@types/node/compatibility/disposable.d.ts
generated
vendored
Normal file
16
em2rp/node_modules/@types/node/compatibility/disposable.d.ts
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Polyfills for the explicit resource management types added in TypeScript 5.2.
|
||||||
|
// TODO: remove once this package no longer supports TS 5.1, and replace with a
|
||||||
|
// <reference> to TypeScript's disposable library in index.d.ts.
|
||||||
|
|
||||||
|
interface SymbolConstructor {
|
||||||
|
readonly dispose: unique symbol;
|
||||||
|
readonly asyncDispose: unique symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Disposable {
|
||||||
|
[Symbol.dispose](): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AsyncDisposable {
|
||||||
|
[Symbol.asyncDispose](): PromiseLike<void>;
|
||||||
|
}
|
9
em2rp/node_modules/@types/node/compatibility/index.d.ts
generated
vendored
Normal file
9
em2rp/node_modules/@types/node/compatibility/index.d.ts
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// Declaration files in this directory contain types relating to TypeScript library features
|
||||||
|
// that are not included in all TypeScript versions supported by DefinitelyTyped, but
|
||||||
|
// which can be made backwards-compatible without needing `typesVersions`.
|
||||||
|
// If adding declarations to this directory, please specify which versions of TypeScript require them,
|
||||||
|
// so that they can be removed when no longer needed.
|
||||||
|
|
||||||
|
/// <reference path="disposable.d.ts" />
|
||||||
|
/// <reference path="indexable.d.ts" />
|
||||||
|
/// <reference path="iterators.d.ts" />
|
23
em2rp/node_modules/@types/node/compatibility/indexable.d.ts
generated
vendored
Normal file
23
em2rp/node_modules/@types/node/compatibility/indexable.d.ts
generated
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Polyfill for ES2022's .at() method on string/array prototypes, added to TypeScript in 4.6.
|
||||||
|
// TODO: these methods are not used within @types/node, and should be removed at the next
|
||||||
|
// major @types/node version; users should include the es2022 TypeScript libraries
|
||||||
|
// if they need these features.
|
||||||
|
|
||||||
|
interface RelativeIndexable<T> {
|
||||||
|
at(index: number): T | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface String extends RelativeIndexable<string> {}
|
||||||
|
interface Array<T> extends RelativeIndexable<T> {}
|
||||||
|
interface ReadonlyArray<T> extends RelativeIndexable<T> {}
|
||||||
|
interface Int8Array extends RelativeIndexable<number> {}
|
||||||
|
interface Uint8Array extends RelativeIndexable<number> {}
|
||||||
|
interface Uint8ClampedArray extends RelativeIndexable<number> {}
|
||||||
|
interface Int16Array extends RelativeIndexable<number> {}
|
||||||
|
interface Uint16Array extends RelativeIndexable<number> {}
|
||||||
|
interface Int32Array extends RelativeIndexable<number> {}
|
||||||
|
interface Uint32Array extends RelativeIndexable<number> {}
|
||||||
|
interface Float32Array extends RelativeIndexable<number> {}
|
||||||
|
interface Float64Array extends RelativeIndexable<number> {}
|
||||||
|
interface BigInt64Array extends RelativeIndexable<bigint> {}
|
||||||
|
interface BigUint64Array extends RelativeIndexable<bigint> {}
|
21
em2rp/node_modules/@types/node/compatibility/iterators.d.ts
generated
vendored
Normal file
21
em2rp/node_modules/@types/node/compatibility/iterators.d.ts
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Backwards-compatible iterator interfaces, augmented with iterator helper methods by lib.esnext.iterator in TypeScript 5.6.
|
||||||
|
// The IterableIterator interface does not contain these methods, which creates assignability issues in places where IteratorObjects
|
||||||
|
// are expected (eg. DOM-compatible APIs) if lib.esnext.iterator is loaded.
|
||||||
|
// Also ensures that iterators returned by the Node API, which inherit from Iterator.prototype, correctly expose the iterator helper methods
|
||||||
|
// if lib.esnext.iterator is loaded.
|
||||||
|
// TODO: remove once this package no longer supports TS 5.5, and replace NodeJS.BuiltinIteratorReturn with BuiltinIteratorReturn.
|
||||||
|
|
||||||
|
// Placeholders for TS <5.6
|
||||||
|
interface IteratorObject<T, TReturn, TNext> {}
|
||||||
|
interface AsyncIteratorObject<T, TReturn, TNext> {}
|
||||||
|
|
||||||
|
declare namespace NodeJS {
|
||||||
|
// Populate iterator methods for TS <5.6
|
||||||
|
interface Iterator<T, TReturn, TNext> extends globalThis.Iterator<T, TReturn, TNext> {}
|
||||||
|
interface AsyncIterator<T, TReturn, TNext> extends globalThis.AsyncIterator<T, TReturn, TNext> {}
|
||||||
|
|
||||||
|
// Polyfill for TS 5.6's instrinsic BuiltinIteratorReturn type, required for DOM-compatible iterators
|
||||||
|
type BuiltinIteratorReturn = ReturnType<any[][typeof Symbol.iterator]> extends
|
||||||
|
globalThis.Iterator<any, infer TReturn> ? TReturn
|
||||||
|
: any;
|
||||||
|
}
|
452
em2rp/node_modules/@types/node/console.d.ts
generated
vendored
Normal file
452
em2rp/node_modules/@types/node/console.d.ts
generated
vendored
Normal file
@ -0,0 +1,452 @@
|
|||||||
|
/**
|
||||||
|
* The `node:console` module provides a simple debugging console that is similar to
|
||||||
|
* the JavaScript console mechanism provided by web browsers.
|
||||||
|
*
|
||||||
|
* The module exports two specific components:
|
||||||
|
*
|
||||||
|
* * A `Console` class with methods such as `console.log()`, `console.error()`, and `console.warn()` that can be used to write to any Node.js stream.
|
||||||
|
* * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
|
||||||
|
* [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
|
||||||
|
*
|
||||||
|
* _**Warning**_: The global console object's methods are neither consistently
|
||||||
|
* synchronous like the browser APIs they resemble, nor are they consistently
|
||||||
|
* asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
|
||||||
|
* more information.
|
||||||
|
*
|
||||||
|
* Example using the global `console`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.log('hello world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints error message and stack trace to stderr:
|
||||||
|
* // Error: Whoops, something bad happened
|
||||||
|
* // at [eval]:5:15
|
||||||
|
* // at Script.runInThisContext (node:vm:132:18)
|
||||||
|
* // at Object.runInThisContext (node:vm:309:38)
|
||||||
|
* // at node:internal/process/execution:77:19
|
||||||
|
* // at [eval]-wrapper:6:22
|
||||||
|
* // at evalScript (node:internal/process/execution:76:60)
|
||||||
|
* // at node:internal/main/eval_string:23:3
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* console.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to stderr
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example using the `Console` class:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const out = getStreamSomehow();
|
||||||
|
* const err = getStreamSomehow();
|
||||||
|
* const myConsole = new console.Console(out, err);
|
||||||
|
*
|
||||||
|
* myConsole.log('hello world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints: [Error: Whoops, something bad happened], to err
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* myConsole.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to err
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
|
||||||
|
*/
|
||||||
|
declare module "console" {
|
||||||
|
import console = require("node:console");
|
||||||
|
export = console;
|
||||||
|
}
|
||||||
|
declare module "node:console" {
|
||||||
|
import { InspectOptions } from "node:util";
|
||||||
|
global {
|
||||||
|
// This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build
|
||||||
|
interface Console {
|
||||||
|
Console: console.ConsoleConstructor;
|
||||||
|
/**
|
||||||
|
* `console.assert()` writes a message if `value` is [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) or omitted. It only
|
||||||
|
* writes a message and does not otherwise affect execution. The output always
|
||||||
|
* starts with `"Assertion failed"`. If provided, `message` is formatted using
|
||||||
|
* [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args).
|
||||||
|
*
|
||||||
|
* If `value` is [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy), nothing happens.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.assert(true, 'does nothing');
|
||||||
|
*
|
||||||
|
* console.assert(false, 'Whoops %s work', 'didn\'t');
|
||||||
|
* // Assertion failed: Whoops didn't work
|
||||||
|
*
|
||||||
|
* console.assert();
|
||||||
|
* // Assertion failed
|
||||||
|
* ```
|
||||||
|
* @since v0.1.101
|
||||||
|
* @param value The value tested for being truthy.
|
||||||
|
* @param message All arguments besides `value` are used as error message.
|
||||||
|
*/
|
||||||
|
assert(value: any, message?: string, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* When `stdout` is a TTY, calling `console.clear()` will attempt to clear the
|
||||||
|
* TTY. When `stdout` is not a TTY, this method does nothing.
|
||||||
|
*
|
||||||
|
* The specific operation of `console.clear()` can vary across operating systems
|
||||||
|
* and terminal types. For most Linux operating systems, `console.clear()` operates similarly to the `clear` shell command. On Windows, `console.clear()` will clear only the output in the
|
||||||
|
* current terminal viewport for the Node.js
|
||||||
|
* binary.
|
||||||
|
* @since v8.3.0
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
/**
|
||||||
|
* Maintains an internal counter specific to `label` and outputs to `stdout` the
|
||||||
|
* number of times `console.count()` has been called with the given `label`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* > console.count()
|
||||||
|
* default: 1
|
||||||
|
* undefined
|
||||||
|
* > console.count('default')
|
||||||
|
* default: 2
|
||||||
|
* undefined
|
||||||
|
* > console.count('abc')
|
||||||
|
* abc: 1
|
||||||
|
* undefined
|
||||||
|
* > console.count('xyz')
|
||||||
|
* xyz: 1
|
||||||
|
* undefined
|
||||||
|
* > console.count('abc')
|
||||||
|
* abc: 2
|
||||||
|
* undefined
|
||||||
|
* > console.count()
|
||||||
|
* default: 3
|
||||||
|
* undefined
|
||||||
|
* >
|
||||||
|
* ```
|
||||||
|
* @since v8.3.0
|
||||||
|
* @param [label='default'] The display label for the counter.
|
||||||
|
*/
|
||||||
|
count(label?: string): void;
|
||||||
|
/**
|
||||||
|
* Resets the internal counter specific to `label`.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* > console.count('abc');
|
||||||
|
* abc: 1
|
||||||
|
* undefined
|
||||||
|
* > console.countReset('abc');
|
||||||
|
* undefined
|
||||||
|
* > console.count('abc');
|
||||||
|
* abc: 1
|
||||||
|
* undefined
|
||||||
|
* >
|
||||||
|
* ```
|
||||||
|
* @since v8.3.0
|
||||||
|
* @param [label='default'] The display label for the counter.
|
||||||
|
*/
|
||||||
|
countReset(label?: string): void;
|
||||||
|
/**
|
||||||
|
* The `console.debug()` function is an alias for {@link log}.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
debug(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Uses [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) on `obj` and prints the resulting string to `stdout`.
|
||||||
|
* This function bypasses any custom `inspect()` function defined on `obj`.
|
||||||
|
* @since v0.1.101
|
||||||
|
*/
|
||||||
|
dir(obj: any, options?: InspectOptions): void;
|
||||||
|
/**
|
||||||
|
* This method calls `console.log()` passing it the arguments received.
|
||||||
|
* This method does not produce any XML formatting.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
dirxml(...data: any[]): void;
|
||||||
|
/**
|
||||||
|
* Prints to `stderr` with newline. Multiple arguments can be passed, with the
|
||||||
|
* first used as the primary message and all additional used as substitution
|
||||||
|
* values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
|
||||||
|
* (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const code = 5;
|
||||||
|
* console.error('error #%d', code);
|
||||||
|
* // Prints: error #5, to stderr
|
||||||
|
* console.error('error', code);
|
||||||
|
* // Prints: error 5, to stderr
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* If formatting elements (e.g. `%d`) are not found in the first string then
|
||||||
|
* [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options) is called on each argument and the
|
||||||
|
* resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
|
||||||
|
* for more information.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
error(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Increases indentation of subsequent lines by spaces for `groupIndentation` length.
|
||||||
|
*
|
||||||
|
* If one or more `label`s are provided, those are printed first without the
|
||||||
|
* additional indentation.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
group(...label: any[]): void;
|
||||||
|
/**
|
||||||
|
* An alias for {@link group}.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
groupCollapsed(...label: any[]): void;
|
||||||
|
/**
|
||||||
|
* Decreases indentation of subsequent lines by spaces for `groupIndentation` length.
|
||||||
|
* @since v8.5.0
|
||||||
|
*/
|
||||||
|
groupEnd(): void;
|
||||||
|
/**
|
||||||
|
* The `console.info()` function is an alias for {@link log}.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
info(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Prints to `stdout` with newline. Multiple arguments can be passed, with the
|
||||||
|
* first used as the primary message and all additional used as substitution
|
||||||
|
* values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html)
|
||||||
|
* (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)).
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const count = 5;
|
||||||
|
* console.log('count: %d', count);
|
||||||
|
* // Prints: count: 5, to stdout
|
||||||
|
* console.log('count:', count);
|
||||||
|
* // Prints: count: 5, to stdout
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
log(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* Try to construct a table with the columns of the properties of `tabularData` (or use `properties`) and rows of `tabularData` and log it. Falls back to just
|
||||||
|
* logging the argument if it can't be parsed as tabular.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* // These can't be parsed as tabular data
|
||||||
|
* console.table(Symbol());
|
||||||
|
* // Symbol()
|
||||||
|
*
|
||||||
|
* console.table(undefined);
|
||||||
|
* // undefined
|
||||||
|
*
|
||||||
|
* console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }]);
|
||||||
|
* // ┌─────────┬─────┬─────┐
|
||||||
|
* // │ (index) │ a │ b │
|
||||||
|
* // ├─────────┼─────┼─────┤
|
||||||
|
* // │ 0 │ 1 │ 'Y' │
|
||||||
|
* // │ 1 │ 'Z' │ 2 │
|
||||||
|
* // └─────────┴─────┴─────┘
|
||||||
|
*
|
||||||
|
* console.table([{ a: 1, b: 'Y' }, { a: 'Z', b: 2 }], ['a']);
|
||||||
|
* // ┌─────────┬─────┐
|
||||||
|
* // │ (index) │ a │
|
||||||
|
* // ├─────────┼─────┤
|
||||||
|
* // │ 0 │ 1 │
|
||||||
|
* // │ 1 │ 'Z' │
|
||||||
|
* // └─────────┴─────┘
|
||||||
|
* ```
|
||||||
|
* @since v10.0.0
|
||||||
|
* @param properties Alternate properties for constructing the table.
|
||||||
|
*/
|
||||||
|
table(tabularData: any, properties?: readonly string[]): void;
|
||||||
|
/**
|
||||||
|
* Starts a timer that can be used to compute the duration of an operation. Timers
|
||||||
|
* are identified by a unique `label`. Use the same `label` when calling {@link timeEnd} to stop the timer and output the elapsed time in
|
||||||
|
* suitable time units to `stdout`. For example, if the elapsed
|
||||||
|
* time is 3869ms, `console.timeEnd()` displays "3.869s".
|
||||||
|
* @since v0.1.104
|
||||||
|
* @param [label='default']
|
||||||
|
*/
|
||||||
|
time(label?: string): void;
|
||||||
|
/**
|
||||||
|
* Stops a timer that was previously started by calling {@link time} and
|
||||||
|
* prints the result to `stdout`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.time('bunch-of-stuff');
|
||||||
|
* // Do a bunch of stuff.
|
||||||
|
* console.timeEnd('bunch-of-stuff');
|
||||||
|
* // Prints: bunch-of-stuff: 225.438ms
|
||||||
|
* ```
|
||||||
|
* @since v0.1.104
|
||||||
|
* @param [label='default']
|
||||||
|
*/
|
||||||
|
timeEnd(label?: string): void;
|
||||||
|
/**
|
||||||
|
* For a timer that was previously started by calling {@link time}, prints
|
||||||
|
* the elapsed time and other `data` arguments to `stdout`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.time('process');
|
||||||
|
* const value = expensiveProcess1(); // Returns 42
|
||||||
|
* console.timeLog('process', value);
|
||||||
|
* // Prints "process: 365.227ms 42".
|
||||||
|
* doExpensiveProcess2(value);
|
||||||
|
* console.timeEnd('process');
|
||||||
|
* ```
|
||||||
|
* @since v10.7.0
|
||||||
|
* @param [label='default']
|
||||||
|
*/
|
||||||
|
timeLog(label?: string, ...data: any[]): void;
|
||||||
|
/**
|
||||||
|
* Prints to `stderr` the string `'Trace: '`, followed by the [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)
|
||||||
|
* formatted message and stack trace to the current position in the code.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.trace('Show me');
|
||||||
|
* // Prints: (stack trace will vary based on where trace is called)
|
||||||
|
* // Trace: Show me
|
||||||
|
* // at repl:2:9
|
||||||
|
* // at REPLServer.defaultEval (repl.js:248:27)
|
||||||
|
* // at bound (domain.js:287:14)
|
||||||
|
* // at REPLServer.runBound [as eval] (domain.js:300:12)
|
||||||
|
* // at REPLServer.<anonymous> (repl.js:412:12)
|
||||||
|
* // at emitOne (events.js:82:20)
|
||||||
|
* // at REPLServer.emit (events.js:169:7)
|
||||||
|
* // at REPLServer.Interface._onLine (readline.js:210:10)
|
||||||
|
* // at REPLServer.Interface._line (readline.js:549:8)
|
||||||
|
* // at REPLServer.Interface._ttyWrite (readline.js:826:14)
|
||||||
|
* ```
|
||||||
|
* @since v0.1.104
|
||||||
|
*/
|
||||||
|
trace(message?: any, ...optionalParams: any[]): void;
|
||||||
|
/**
|
||||||
|
* The `console.warn()` function is an alias for {@link error}.
|
||||||
|
* @since v0.1.100
|
||||||
|
*/
|
||||||
|
warn(message?: any, ...optionalParams: any[]): void;
|
||||||
|
// --- Inspector mode only ---
|
||||||
|
/**
|
||||||
|
* This method does not display anything unless used in the inspector. The `console.profile()`
|
||||||
|
* method starts a JavaScript CPU profile with an optional label until {@link profileEnd}
|
||||||
|
* is called. The profile is then added to the Profile panel of the inspector.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.profile('MyLabel');
|
||||||
|
* // Some code
|
||||||
|
* console.profileEnd('MyLabel');
|
||||||
|
* // Adds the profile 'MyLabel' to the Profiles panel of the inspector.
|
||||||
|
* ```
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
profile(label?: string): void;
|
||||||
|
/**
|
||||||
|
* This method does not display anything unless used in the inspector. Stops the current
|
||||||
|
* JavaScript CPU profiling session if one has been started and prints the report to the
|
||||||
|
* Profiles panel of the inspector. See {@link profile} for an example.
|
||||||
|
*
|
||||||
|
* If this method is called without a label, the most recently started profile is stopped.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
profileEnd(label?: string): void;
|
||||||
|
/**
|
||||||
|
* This method does not display anything unless used in the inspector. The `console.timeStamp()`
|
||||||
|
* method adds an event with the label `'label'` to the Timeline panel of the inspector.
|
||||||
|
* @since v8.0.0
|
||||||
|
*/
|
||||||
|
timeStamp(label?: string): void;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The `console` module provides a simple debugging console that is similar to the
|
||||||
|
* JavaScript console mechanism provided by web browsers.
|
||||||
|
*
|
||||||
|
* The module exports two specific components:
|
||||||
|
*
|
||||||
|
* * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream.
|
||||||
|
* * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and
|
||||||
|
* [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module.
|
||||||
|
*
|
||||||
|
* _**Warning**_: The global console object's methods are neither consistently
|
||||||
|
* synchronous like the browser APIs they resemble, nor are they consistently
|
||||||
|
* asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for
|
||||||
|
* more information.
|
||||||
|
*
|
||||||
|
* Example using the global `console`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* console.log('hello world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to stdout
|
||||||
|
* console.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints error message and stack trace to stderr:
|
||||||
|
* // Error: Whoops, something bad happened
|
||||||
|
* // at [eval]:5:15
|
||||||
|
* // at Script.runInThisContext (node:vm:132:18)
|
||||||
|
* // at Object.runInThisContext (node:vm:309:38)
|
||||||
|
* // at node:internal/process/execution:77:19
|
||||||
|
* // at [eval]-wrapper:6:22
|
||||||
|
* // at evalScript (node:internal/process/execution:76:60)
|
||||||
|
* // at node:internal/main/eval_string:23:3
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* console.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to stderr
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example using the `Console` class:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const out = getStreamSomehow();
|
||||||
|
* const err = getStreamSomehow();
|
||||||
|
* const myConsole = new console.Console(out, err);
|
||||||
|
*
|
||||||
|
* myConsole.log('hello world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.log('hello %s', 'world');
|
||||||
|
* // Prints: hello world, to out
|
||||||
|
* myConsole.error(new Error('Whoops, something bad happened'));
|
||||||
|
* // Prints: [Error: Whoops, something bad happened], to err
|
||||||
|
*
|
||||||
|
* const name = 'Will Robinson';
|
||||||
|
* myConsole.warn(`Danger ${name}! Danger!`);
|
||||||
|
* // Prints: Danger Will Robinson! Danger!, to err
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v22.x/lib/console.js)
|
||||||
|
*/
|
||||||
|
namespace console {
|
||||||
|
interface ConsoleConstructorOptions {
|
||||||
|
stdout: NodeJS.WritableStream;
|
||||||
|
stderr?: NodeJS.WritableStream | undefined;
|
||||||
|
/**
|
||||||
|
* Ignore errors when writing to the underlying streams.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
ignoreErrors?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Set color support for this `Console` instance. Setting to true enables coloring while inspecting
|
||||||
|
* values. Setting to `false` disables coloring while inspecting values. Setting to `'auto'` makes color
|
||||||
|
* support depend on the value of the `isTTY` property and the value returned by `getColorDepth()` on the
|
||||||
|
* respective stream. This option can not be used, if `inspectOptions.colors` is set as well.
|
||||||
|
* @default auto
|
||||||
|
*/
|
||||||
|
colorMode?: boolean | "auto" | undefined;
|
||||||
|
/**
|
||||||
|
* Specifies options that are passed along to
|
||||||
|
* [`util.inspect()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilinspectobject-options).
|
||||||
|
*/
|
||||||
|
inspectOptions?: InspectOptions | undefined;
|
||||||
|
/**
|
||||||
|
* Set group indentation.
|
||||||
|
* @default 2
|
||||||
|
*/
|
||||||
|
groupIndentation?: number | undefined;
|
||||||
|
}
|
||||||
|
interface ConsoleConstructor {
|
||||||
|
prototype: Console;
|
||||||
|
new(stdout: NodeJS.WritableStream, stderr?: NodeJS.WritableStream, ignoreErrors?: boolean): Console;
|
||||||
|
new(options: ConsoleConstructorOptions): Console;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var console: Console;
|
||||||
|
}
|
||||||
|
export = globalThis.console;
|
||||||
|
}
|
21
em2rp/node_modules/@types/node/constants.d.ts
generated
vendored
Normal file
21
em2rp/node_modules/@types/node/constants.d.ts
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @deprecated The `node:constants` module is deprecated. When requiring access to constants
|
||||||
|
* relevant to specific Node.js builtin modules, developers should instead refer
|
||||||
|
* to the `constants` property exposed by the relevant module. For instance,
|
||||||
|
* `require('node:fs').constants` and `require('node:os').constants`.
|
||||||
|
*/
|
||||||
|
declare module "constants" {
|
||||||
|
const constants:
|
||||||
|
& typeof import("node:os").constants.dlopen
|
||||||
|
& typeof import("node:os").constants.errno
|
||||||
|
& typeof import("node:os").constants.priority
|
||||||
|
& typeof import("node:os").constants.signals
|
||||||
|
& typeof import("node:fs").constants
|
||||||
|
& typeof import("node:crypto").constants;
|
||||||
|
export = constants;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module "node:constants" {
|
||||||
|
import constants = require("constants");
|
||||||
|
export = constants;
|
||||||
|
}
|
4509
em2rp/node_modules/@types/node/crypto.d.ts
generated
vendored
Normal file
4509
em2rp/node_modules/@types/node/crypto.d.ts
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
599
em2rp/node_modules/@types/node/dgram.d.ts
generated
vendored
Normal file
599
em2rp/node_modules/@types/node/dgram.d.ts
generated
vendored
Normal file
@ -0,0 +1,599 @@
|
|||||||
|
/**
|
||||||
|
* The `node:dgram` module provides an implementation of UDP datagram sockets.
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
*
|
||||||
|
* const server = dgram.createSocket('udp4');
|
||||||
|
*
|
||||||
|
* server.on('error', (err) => {
|
||||||
|
* console.error(`server error:\n${err.stack}`);
|
||||||
|
* server.close();
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('message', (msg, rinfo) => {
|
||||||
|
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('listening', () => {
|
||||||
|
* const address = server.address();
|
||||||
|
* console.log(`server listening ${address.address}:${address.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.bind(41234);
|
||||||
|
* // Prints: server listening 0.0.0.0:41234
|
||||||
|
* ```
|
||||||
|
* @see [source](https://github.com/nodejs/node/blob/v22.x/lib/dgram.js)
|
||||||
|
*/
|
||||||
|
declare module "dgram" {
|
||||||
|
import { AddressInfo, BlockList } from "node:net";
|
||||||
|
import * as dns from "node:dns";
|
||||||
|
import { Abortable, EventEmitter } from "node:events";
|
||||||
|
interface RemoteInfo {
|
||||||
|
address: string;
|
||||||
|
family: "IPv4" | "IPv6";
|
||||||
|
port: number;
|
||||||
|
size: number;
|
||||||
|
}
|
||||||
|
interface BindOptions {
|
||||||
|
port?: number | undefined;
|
||||||
|
address?: string | undefined;
|
||||||
|
exclusive?: boolean | undefined;
|
||||||
|
fd?: number | undefined;
|
||||||
|
}
|
||||||
|
type SocketType = "udp4" | "udp6";
|
||||||
|
interface SocketOptions extends Abortable {
|
||||||
|
type: SocketType;
|
||||||
|
reuseAddr?: boolean | undefined;
|
||||||
|
reusePort?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* @default false
|
||||||
|
*/
|
||||||
|
ipv6Only?: boolean | undefined;
|
||||||
|
recvBufferSize?: number | undefined;
|
||||||
|
sendBufferSize?: number | undefined;
|
||||||
|
lookup?:
|
||||||
|
| ((
|
||||||
|
hostname: string,
|
||||||
|
options: dns.LookupOneOptions,
|
||||||
|
callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void,
|
||||||
|
) => void)
|
||||||
|
| undefined;
|
||||||
|
receiveBlockList?: BlockList | undefined;
|
||||||
|
sendBlockList?: BlockList | undefined;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates a `dgram.Socket` object. Once the socket is created, calling `socket.bind()` will instruct the socket to begin listening for datagram
|
||||||
|
* messages. When `address` and `port` are not passed to `socket.bind()` the
|
||||||
|
* method will bind the socket to the "all interfaces" address on a random port
|
||||||
|
* (it does the right thing for both `udp4` and `udp6` sockets). The bound address
|
||||||
|
* and port can be retrieved using `socket.address().address` and `socket.address().port`.
|
||||||
|
*
|
||||||
|
* If the `signal` option is enabled, calling `.abort()` on the corresponding `AbortController` is similar to calling `.close()` on the socket:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const controller = new AbortController();
|
||||||
|
* const { signal } = controller;
|
||||||
|
* const server = dgram.createSocket({ type: 'udp4', signal });
|
||||||
|
* server.on('message', (msg, rinfo) => {
|
||||||
|
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||||
|
* });
|
||||||
|
* // Later, when you want to close the server.
|
||||||
|
* controller.abort();
|
||||||
|
* ```
|
||||||
|
* @since v0.11.13
|
||||||
|
* @param options Available options are:
|
||||||
|
* @param callback Attached as a listener for `'message'` events. Optional.
|
||||||
|
*/
|
||||||
|
function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
|
||||||
|
function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
|
||||||
|
/**
|
||||||
|
* Encapsulates the datagram functionality.
|
||||||
|
*
|
||||||
|
* New instances of `dgram.Socket` are created using {@link createSocket}.
|
||||||
|
* The `new` keyword is not to be used to create `dgram.Socket` instances.
|
||||||
|
* @since v0.1.99
|
||||||
|
*/
|
||||||
|
class Socket extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Tells the kernel to join a multicast group at the given `multicastAddress` and `multicastInterface` using the `IP_ADD_MEMBERSHIP` socket option. If the `multicastInterface` argument is not
|
||||||
|
* specified, the operating system will choose
|
||||||
|
* one interface and will add membership to it. To add membership to every
|
||||||
|
* available interface, call `addMembership` multiple times, once per interface.
|
||||||
|
*
|
||||||
|
* When called on an unbound socket, this method will implicitly bind to a random
|
||||||
|
* port, listening on all interfaces.
|
||||||
|
*
|
||||||
|
* When sharing a UDP socket across multiple `cluster` workers, the`socket.addMembership()` function must be called only once or an`EADDRINUSE` error will occur:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import cluster from 'node:cluster';
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
*
|
||||||
|
* if (cluster.isPrimary) {
|
||||||
|
* cluster.fork(); // Works ok.
|
||||||
|
* cluster.fork(); // Fails with EADDRINUSE.
|
||||||
|
* } else {
|
||||||
|
* const s = dgram.createSocket('udp4');
|
||||||
|
* s.bind(1234, () => {
|
||||||
|
* s.addMembership('224.0.0.114');
|
||||||
|
* });
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
* @since v0.6.9
|
||||||
|
*/
|
||||||
|
addMembership(multicastAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* Returns an object containing the address information for a socket.
|
||||||
|
* For UDP sockets, this object will contain `address`, `family`, and `port` properties.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.1.99
|
||||||
|
*/
|
||||||
|
address(): AddressInfo;
|
||||||
|
/**
|
||||||
|
* For UDP sockets, causes the `dgram.Socket` to listen for datagram
|
||||||
|
* messages on a named `port` and optional `address`. If `port` is not
|
||||||
|
* specified or is `0`, the operating system will attempt to bind to a
|
||||||
|
* random port. If `address` is not specified, the operating system will
|
||||||
|
* attempt to listen on all addresses. Once binding is complete, a `'listening'` event is emitted and the optional `callback` function is
|
||||||
|
* called.
|
||||||
|
*
|
||||||
|
* Specifying both a `'listening'` event listener and passing a `callback` to the `socket.bind()` method is not harmful but not very
|
||||||
|
* useful.
|
||||||
|
*
|
||||||
|
* A bound datagram socket keeps the Node.js process running to receive
|
||||||
|
* datagram messages.
|
||||||
|
*
|
||||||
|
* If binding fails, an `'error'` event is generated. In rare case (e.g.
|
||||||
|
* attempting to bind with a closed socket), an `Error` may be thrown.
|
||||||
|
*
|
||||||
|
* Example of a UDP server listening on port 41234:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
*
|
||||||
|
* const server = dgram.createSocket('udp4');
|
||||||
|
*
|
||||||
|
* server.on('error', (err) => {
|
||||||
|
* console.error(`server error:\n${err.stack}`);
|
||||||
|
* server.close();
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('message', (msg, rinfo) => {
|
||||||
|
* console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.on('listening', () => {
|
||||||
|
* const address = server.address();
|
||||||
|
* console.log(`server listening ${address.address}:${address.port}`);
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* server.bind(41234);
|
||||||
|
* // Prints: server listening 0.0.0.0:41234
|
||||||
|
* ```
|
||||||
|
* @since v0.1.99
|
||||||
|
* @param callback with no parameters. Called when binding is complete.
|
||||||
|
*/
|
||||||
|
bind(port?: number, address?: string, callback?: () => void): this;
|
||||||
|
bind(port?: number, callback?: () => void): this;
|
||||||
|
bind(callback?: () => void): this;
|
||||||
|
bind(options: BindOptions, callback?: () => void): this;
|
||||||
|
/**
|
||||||
|
* Close the underlying socket and stop listening for data on it. If a callback is
|
||||||
|
* provided, it is added as a listener for the `'close'` event.
|
||||||
|
* @since v0.1.99
|
||||||
|
* @param callback Called when the socket has been closed.
|
||||||
|
*/
|
||||||
|
close(callback?: () => void): this;
|
||||||
|
/**
|
||||||
|
* Associates the `dgram.Socket` to a remote address and port. Every
|
||||||
|
* message sent by this handle is automatically sent to that destination. Also,
|
||||||
|
* the socket will only receive messages from that remote peer.
|
||||||
|
* Trying to call `connect()` on an already connected socket will result
|
||||||
|
* in an `ERR_SOCKET_DGRAM_IS_CONNECTED` exception. If `address` is not
|
||||||
|
* provided, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets)
|
||||||
|
* will be used by default. Once the connection is complete, a `'connect'` event
|
||||||
|
* is emitted and the optional `callback` function is called. In case of failure,
|
||||||
|
* the `callback` is called or, failing this, an `'error'` event is emitted.
|
||||||
|
* @since v12.0.0
|
||||||
|
* @param callback Called when the connection is completed or on error.
|
||||||
|
*/
|
||||||
|
connect(port: number, address?: string, callback?: () => void): void;
|
||||||
|
connect(port: number, callback: () => void): void;
|
||||||
|
/**
|
||||||
|
* A synchronous function that disassociates a connected `dgram.Socket` from
|
||||||
|
* its remote address. Trying to call `disconnect()` on an unbound or already
|
||||||
|
* disconnected socket will result in an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception.
|
||||||
|
* @since v12.0.0
|
||||||
|
*/
|
||||||
|
disconnect(): void;
|
||||||
|
/**
|
||||||
|
* Instructs the kernel to leave a multicast group at `multicastAddress` using the `IP_DROP_MEMBERSHIP` socket option. This method is automatically called by the
|
||||||
|
* kernel when the socket is closed or the process terminates, so most apps will
|
||||||
|
* never have reason to call this.
|
||||||
|
*
|
||||||
|
* If `multicastInterface` is not specified, the operating system will attempt to
|
||||||
|
* drop membership on all valid interfaces.
|
||||||
|
* @since v0.6.9
|
||||||
|
*/
|
||||||
|
dropMembership(multicastAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
* @return the `SO_RCVBUF` socket receive buffer size in bytes.
|
||||||
|
*/
|
||||||
|
getRecvBufferSize(): number;
|
||||||
|
/**
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
* @return the `SO_SNDBUF` socket send buffer size in bytes.
|
||||||
|
*/
|
||||||
|
getSendBufferSize(): number;
|
||||||
|
/**
|
||||||
|
* @since v18.8.0, v16.19.0
|
||||||
|
* @return Number of bytes queued for sending.
|
||||||
|
*/
|
||||||
|
getSendQueueSize(): number;
|
||||||
|
/**
|
||||||
|
* @since v18.8.0, v16.19.0
|
||||||
|
* @return Number of send requests currently in the queue awaiting to be processed.
|
||||||
|
*/
|
||||||
|
getSendQueueCount(): number;
|
||||||
|
/**
|
||||||
|
* By default, binding a socket will cause it to block the Node.js process from
|
||||||
|
* exiting as long as the socket is open. The `socket.unref()` method can be used
|
||||||
|
* to exclude the socket from the reference counting that keeps the Node.js
|
||||||
|
* process active. The `socket.ref()` method adds the socket back to the reference
|
||||||
|
* counting and restores the default behavior.
|
||||||
|
*
|
||||||
|
* Calling `socket.ref()` multiples times will have no additional effect.
|
||||||
|
*
|
||||||
|
* The `socket.ref()` method returns a reference to the socket so calls can be
|
||||||
|
* chained.
|
||||||
|
* @since v0.9.1
|
||||||
|
*/
|
||||||
|
ref(): this;
|
||||||
|
/**
|
||||||
|
* Returns an object containing the `address`, `family`, and `port` of the remote
|
||||||
|
* endpoint. This method throws an `ERR_SOCKET_DGRAM_NOT_CONNECTED` exception
|
||||||
|
* if the socket is not connected.
|
||||||
|
* @since v12.0.0
|
||||||
|
*/
|
||||||
|
remoteAddress(): AddressInfo;
|
||||||
|
/**
|
||||||
|
* Broadcasts a datagram on the socket.
|
||||||
|
* For connectionless sockets, the destination `port` and `address` must be
|
||||||
|
* specified. Connected sockets, on the other hand, will use their associated
|
||||||
|
* remote endpoint, so the `port` and `address` arguments must not be set.
|
||||||
|
*
|
||||||
|
* The `msg` argument contains the message to be sent.
|
||||||
|
* Depending on its type, different behavior can apply. If `msg` is a `Buffer`,
|
||||||
|
* any `TypedArray` or a `DataView`,
|
||||||
|
* the `offset` and `length` specify the offset within the `Buffer` where the
|
||||||
|
* message begins and the number of bytes in the message, respectively.
|
||||||
|
* If `msg` is a `String`, then it is automatically converted to a `Buffer` with `'utf8'` encoding. With messages that
|
||||||
|
* contain multi-byte characters, `offset` and `length` will be calculated with
|
||||||
|
* respect to `byte length` and not the character position.
|
||||||
|
* If `msg` is an array, `offset` and `length` must not be specified.
|
||||||
|
*
|
||||||
|
* The `address` argument is a string. If the value of `address` is a host name,
|
||||||
|
* DNS will be used to resolve the address of the host. If `address` is not
|
||||||
|
* provided or otherwise nullish, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets) will be used by default.
|
||||||
|
*
|
||||||
|
* If the socket has not been previously bound with a call to `bind`, the socket
|
||||||
|
* is assigned a random port number and is bound to the "all interfaces" address
|
||||||
|
* (`'0.0.0.0'` for `udp4` sockets, `'::0'` for `udp6` sockets.)
|
||||||
|
*
|
||||||
|
* An optional `callback` function may be specified to as a way of reporting
|
||||||
|
* DNS errors or for determining when it is safe to reuse the `buf` object.
|
||||||
|
* DNS lookups delay the time to send for at least one tick of the
|
||||||
|
* Node.js event loop.
|
||||||
|
*
|
||||||
|
* The only way to know for sure that the datagram has been sent is by using a `callback`. If an error occurs and a `callback` is given, the error will be
|
||||||
|
* passed as the first argument to the `callback`. If a `callback` is not given,
|
||||||
|
* the error is emitted as an `'error'` event on the `socket` object.
|
||||||
|
*
|
||||||
|
* Offset and length are optional but both _must_ be set if either are used.
|
||||||
|
* They are supported only when the first argument is a `Buffer`, a `TypedArray`,
|
||||||
|
* or a `DataView`.
|
||||||
|
*
|
||||||
|
* This method throws `ERR_SOCKET_BAD_PORT` if called on an unbound socket.
|
||||||
|
*
|
||||||
|
* Example of sending a UDP packet to a port on `localhost`;
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const message = Buffer.from('Some bytes');
|
||||||
|
* const client = dgram.createSocket('udp4');
|
||||||
|
* client.send(message, 41234, 'localhost', (err) => {
|
||||||
|
* client.close();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Example of sending a UDP packet composed of multiple buffers to a port on`127.0.0.1`;
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const buf1 = Buffer.from('Some ');
|
||||||
|
* const buf2 = Buffer.from('bytes');
|
||||||
|
* const client = dgram.createSocket('udp4');
|
||||||
|
* client.send([buf1, buf2], 41234, (err) => {
|
||||||
|
* client.close();
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Sending multiple buffers might be faster or slower depending on the
|
||||||
|
* application and operating system. Run benchmarks to
|
||||||
|
* determine the optimal strategy on a case-by-case basis. Generally speaking,
|
||||||
|
* however, sending multiple buffers is faster.
|
||||||
|
*
|
||||||
|
* Example of sending a UDP packet using a socket connected to a port on `localhost`:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* import dgram from 'node:dgram';
|
||||||
|
* import { Buffer } from 'node:buffer';
|
||||||
|
*
|
||||||
|
* const message = Buffer.from('Some bytes');
|
||||||
|
* const client = dgram.createSocket('udp4');
|
||||||
|
* client.connect(41234, 'localhost', (err) => {
|
||||||
|
* client.send(message, (err) => {
|
||||||
|
* client.close();
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v0.1.99
|
||||||
|
* @param msg Message to be sent.
|
||||||
|
* @param offset Offset in the buffer where the message starts.
|
||||||
|
* @param length Number of bytes in the message.
|
||||||
|
* @param port Destination port.
|
||||||
|
* @param address Destination host name or IP address.
|
||||||
|
* @param callback Called when the message has been sent.
|
||||||
|
*/
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||||
|
port?: number,
|
||||||
|
address?: string,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||||
|
port?: number,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView | readonly any[],
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
port?: number,
|
||||||
|
address?: string,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
port?: number,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
send(
|
||||||
|
msg: string | NodeJS.ArrayBufferView,
|
||||||
|
offset: number,
|
||||||
|
length: number,
|
||||||
|
callback?: (error: Error | null, bytes: number) => void,
|
||||||
|
): void;
|
||||||
|
/**
|
||||||
|
* Sets or clears the `SO_BROADCAST` socket option. When set to `true`, UDP
|
||||||
|
* packets may be sent to a local interface's broadcast address.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.6.9
|
||||||
|
*/
|
||||||
|
setBroadcast(flag: boolean): void;
|
||||||
|
/**
|
||||||
|
* _All references to scope in this section are referring to [IPv6 Zone Indices](https://en.wikipedia.org/wiki/IPv6_address#Scoped_literal_IPv6_addresses), which are defined by [RFC
|
||||||
|
* 4007](https://tools.ietf.org/html/rfc4007). In string form, an IP_
|
||||||
|
* _with a scope index is written as `'IP%scope'` where scope is an interface name_
|
||||||
|
* _or interface number._
|
||||||
|
*
|
||||||
|
* Sets the default outgoing multicast interface of the socket to a chosen
|
||||||
|
* interface or back to system interface selection. The `multicastInterface` must
|
||||||
|
* be a valid string representation of an IP from the socket's family.
|
||||||
|
*
|
||||||
|
* For IPv4 sockets, this should be the IP configured for the desired physical
|
||||||
|
* interface. All packets sent to multicast on the socket will be sent on the
|
||||||
|
* interface determined by the most recent successful use of this call.
|
||||||
|
*
|
||||||
|
* For IPv6 sockets, `multicastInterface` should include a scope to indicate the
|
||||||
|
* interface as in the examples that follow. In IPv6, individual `send` calls can
|
||||||
|
* also use explicit scope in addresses, so only packets sent to a multicast
|
||||||
|
* address without specifying an explicit scope are affected by the most recent
|
||||||
|
* successful use of this call.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
*
|
||||||
|
* #### Example: IPv6 outgoing multicast interface
|
||||||
|
*
|
||||||
|
* On most systems, where scope format uses the interface name:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const socket = dgram.createSocket('udp6');
|
||||||
|
*
|
||||||
|
* socket.bind(1234, () => {
|
||||||
|
* socket.setMulticastInterface('::%eth1');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* On Windows, where scope format uses an interface number:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const socket = dgram.createSocket('udp6');
|
||||||
|
*
|
||||||
|
* socket.bind(1234, () => {
|
||||||
|
* socket.setMulticastInterface('::%2');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* #### Example: IPv4 outgoing multicast interface
|
||||||
|
*
|
||||||
|
* All systems use an IP of the host on the desired physical interface:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* const socket = dgram.createSocket('udp4');
|
||||||
|
*
|
||||||
|
* socket.bind(1234, () => {
|
||||||
|
* socket.setMulticastInterface('10.0.0.2');
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
* @since v8.6.0
|
||||||
|
*/
|
||||||
|
setMulticastInterface(multicastInterface: string): void;
|
||||||
|
/**
|
||||||
|
* Sets or clears the `IP_MULTICAST_LOOP` socket option. When set to `true`,
|
||||||
|
* multicast packets will also be received on the local interface.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.3.8
|
||||||
|
*/
|
||||||
|
setMulticastLoopback(flag: boolean): boolean;
|
||||||
|
/**
|
||||||
|
* Sets the `IP_MULTICAST_TTL` socket option. While TTL generally stands for
|
||||||
|
* "Time to Live", in this context it specifies the number of IP hops that a
|
||||||
|
* packet is allowed to travel through, specifically for multicast traffic. Each
|
||||||
|
* router or gateway that forwards a packet decrements the TTL. If the TTL is
|
||||||
|
* decremented to 0 by a router, it will not be forwarded.
|
||||||
|
*
|
||||||
|
* The `ttl` argument may be between 0 and 255\. The default on most systems is `1`.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.3.8
|
||||||
|
*/
|
||||||
|
setMulticastTTL(ttl: number): number;
|
||||||
|
/**
|
||||||
|
* Sets the `SO_RCVBUF` socket option. Sets the maximum socket receive buffer
|
||||||
|
* in bytes.
|
||||||
|
*
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
*/
|
||||||
|
setRecvBufferSize(size: number): void;
|
||||||
|
/**
|
||||||
|
* Sets the `SO_SNDBUF` socket option. Sets the maximum socket send buffer
|
||||||
|
* in bytes.
|
||||||
|
*
|
||||||
|
* This method throws `ERR_SOCKET_BUFFER_SIZE` if called on an unbound socket.
|
||||||
|
* @since v8.7.0
|
||||||
|
*/
|
||||||
|
setSendBufferSize(size: number): void;
|
||||||
|
/**
|
||||||
|
* Sets the `IP_TTL` socket option. While TTL generally stands for "Time to Live",
|
||||||
|
* in this context it specifies the number of IP hops that a packet is allowed to
|
||||||
|
* travel through. Each router or gateway that forwards a packet decrements the
|
||||||
|
* TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.
|
||||||
|
* Changing TTL values is typically done for network probes or when multicasting.
|
||||||
|
*
|
||||||
|
* The `ttl` argument may be between 1 and 255\. The default on most systems
|
||||||
|
* is 64.
|
||||||
|
*
|
||||||
|
* This method throws `EBADF` if called on an unbound socket.
|
||||||
|
* @since v0.1.101
|
||||||
|
*/
|
||||||
|
setTTL(ttl: number): number;
|
||||||
|
/**
|
||||||
|
* By default, binding a socket will cause it to block the Node.js process from
|
||||||
|
* exiting as long as the socket is open. The `socket.unref()` method can be used
|
||||||
|
* to exclude the socket from the reference counting that keeps the Node.js
|
||||||
|
* process active, allowing the process to exit even if the socket is still
|
||||||
|
* listening.
|
||||||
|
*
|
||||||
|
* Calling `socket.unref()` multiple times will have no additional effect.
|
||||||
|
*
|
||||||
|
* The `socket.unref()` method returns a reference to the socket so calls can be
|
||||||
|
* chained.
|
||||||
|
* @since v0.9.1
|
||||||
|
*/
|
||||||
|
unref(): this;
|
||||||
|
/**
|
||||||
|
* Tells the kernel to join a source-specific multicast channel at the given `sourceAddress` and `groupAddress`, using the `multicastInterface` with the `IP_ADD_SOURCE_MEMBERSHIP` socket
|
||||||
|
* option. If the `multicastInterface` argument
|
||||||
|
* is not specified, the operating system will choose one interface and will add
|
||||||
|
* membership to it. To add membership to every available interface, call `socket.addSourceSpecificMembership()` multiple times, once per interface.
|
||||||
|
*
|
||||||
|
* When called on an unbound socket, this method will implicitly bind to a random
|
||||||
|
* port, listening on all interfaces.
|
||||||
|
* @since v13.1.0, v12.16.0
|
||||||
|
*/
|
||||||
|
addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* Instructs the kernel to leave a source-specific multicast channel at the given `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP` socket option. This method is
|
||||||
|
* automatically called by the kernel when the
|
||||||
|
* socket is closed or the process terminates, so most apps will never have
|
||||||
|
* reason to call this.
|
||||||
|
*
|
||||||
|
* If `multicastInterface` is not specified, the operating system will attempt to
|
||||||
|
* drop membership on all valid interfaces.
|
||||||
|
* @since v13.1.0, v12.16.0
|
||||||
|
*/
|
||||||
|
dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
|
||||||
|
/**
|
||||||
|
* events.EventEmitter
|
||||||
|
* 1. close
|
||||||
|
* 2. connect
|
||||||
|
* 3. error
|
||||||
|
* 4. listening
|
||||||
|
* 5. message
|
||||||
|
*/
|
||||||
|
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
addListener(event: "close", listener: () => void): this;
|
||||||
|
addListener(event: "connect", listener: () => void): this;
|
||||||
|
addListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
addListener(event: "listening", listener: () => void): this;
|
||||||
|
addListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
emit(event: string | symbol, ...args: any[]): boolean;
|
||||||
|
emit(event: "close"): boolean;
|
||||||
|
emit(event: "connect"): boolean;
|
||||||
|
emit(event: "error", err: Error): boolean;
|
||||||
|
emit(event: "listening"): boolean;
|
||||||
|
emit(event: "message", msg: Buffer, rinfo: RemoteInfo): boolean;
|
||||||
|
on(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
on(event: "close", listener: () => void): this;
|
||||||
|
on(event: "connect", listener: () => void): this;
|
||||||
|
on(event: "error", listener: (err: Error) => void): this;
|
||||||
|
on(event: "listening", listener: () => void): this;
|
||||||
|
on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
once(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
once(event: "close", listener: () => void): this;
|
||||||
|
once(event: "connect", listener: () => void): this;
|
||||||
|
once(event: "error", listener: (err: Error) => void): this;
|
||||||
|
once(event: "listening", listener: () => void): this;
|
||||||
|
once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependListener(event: "close", listener: () => void): this;
|
||||||
|
prependListener(event: "connect", listener: () => void): this;
|
||||||
|
prependListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
prependListener(event: "listening", listener: () => void): this;
|
||||||
|
prependListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||||
|
prependOnceListener(event: "close", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "connect", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "error", listener: (err: Error) => void): this;
|
||||||
|
prependOnceListener(event: "listening", listener: () => void): this;
|
||||||
|
prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
|
||||||
|
/**
|
||||||
|
* Calls `socket.close()` and returns a promise that fulfills when the socket has closed.
|
||||||
|
* @since v20.5.0
|
||||||
|
*/
|
||||||
|
[Symbol.asyncDispose](): Promise<void>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
declare module "node:dgram" {
|
||||||
|
export * from "dgram";
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user