fix(qb-core): post-update recovery + centralizare notify 17mov_Hud
Restaurat jobs.lua din git (Quasar fork a suprascris joburile 17mov). Adăugat item map în items.lua (lipsea, rupt rv-maphold). Setat licences.driver = false în config.lua. Override QBCore.Functions.Notify + QBCore:Notify event → 17mov_Hud:ShowNotification (toate notificările merg automat prin 17mov_Hud).
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
define.lua
|
||||
MySQL.lua
|
||||
@@ -0,0 +1,155 @@
|
||||
local promise = promise
|
||||
local Await = Citizen.Await
|
||||
local resourceName = GetCurrentResourceName()
|
||||
local GetResourceState = GetResourceState
|
||||
|
||||
local options = {
|
||||
return_callback_errors = false
|
||||
}
|
||||
|
||||
for i = 1, GetNumResourceMetadata(resourceName, 'mysql_option') do
|
||||
local option = GetResourceMetadata(resourceName, 'mysql_option', i - 1)
|
||||
options[option] = true
|
||||
end
|
||||
|
||||
local function await(fn, query, parameters)
|
||||
local p = promise.new()
|
||||
|
||||
fn(nil, query, parameters, function(result, error)
|
||||
if error then
|
||||
return p:reject(error)
|
||||
end
|
||||
|
||||
p:resolve(result)
|
||||
end, resourceName, true)
|
||||
|
||||
return Await(p)
|
||||
end
|
||||
|
||||
local type = type
|
||||
local queryStore = {}
|
||||
|
||||
local function safeArgs(query, parameters, cb, transaction)
|
||||
local queryType = type(query)
|
||||
|
||||
if queryType == 'number' then
|
||||
query = queryStore[query]
|
||||
assert(query, "First argument received invalid query store reference")
|
||||
elseif transaction then
|
||||
if queryType ~= 'table' then
|
||||
error(("First argument expected table, received '%s'"):format(query))
|
||||
end
|
||||
elseif queryType ~= 'string' then
|
||||
error(("First argument expected string, received '%s'"):format(query))
|
||||
end
|
||||
|
||||
if parameters then
|
||||
local paramType = type(parameters)
|
||||
|
||||
if paramType ~= 'table' and paramType ~= 'function' then
|
||||
error(("Second argument expected table or function, received '%s'"):format(parameters))
|
||||
end
|
||||
|
||||
if paramType == 'function' or parameters.__cfx_functionReference then
|
||||
cb = parameters
|
||||
parameters = nil
|
||||
end
|
||||
end
|
||||
|
||||
if cb and parameters then
|
||||
local cbType = type(cb)
|
||||
|
||||
if cbType ~= 'function' and (cbType == 'table' and not cb.__cfx_functionReference) then
|
||||
error(("Third argument expected function, received '%s'"):format(cb))
|
||||
end
|
||||
end
|
||||
|
||||
return query, parameters, cb
|
||||
end
|
||||
|
||||
local oxmysql = exports.oxmysql
|
||||
|
||||
local mysql_method_mt = {
|
||||
__call = function(self, query, parameters, cb)
|
||||
query, parameters, cb = safeArgs(query, parameters, cb, self.method == 'transaction')
|
||||
return oxmysql[self.method](nil, query, parameters, cb, resourceName, options.return_callback_errors)
|
||||
end
|
||||
}
|
||||
|
||||
local MySQL = setmetatable(MySQL or {}, {
|
||||
__index = function(_, index)
|
||||
return function(...)
|
||||
return oxmysql[index](nil, ...)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
for _, method in pairs({
|
||||
'scalar', 'single', 'query', 'insert', 'update', 'prepare', 'transaction', 'rawExecute',
|
||||
}) do
|
||||
MySQL[method] = setmetatable({
|
||||
method = method,
|
||||
await = function(query, parameters)
|
||||
query, parameters = safeArgs(query, parameters, nil, method == 'transaction')
|
||||
return await(oxmysql[method], query, parameters)
|
||||
end
|
||||
}, mysql_method_mt)
|
||||
end
|
||||
|
||||
local alias = {
|
||||
fetchAll = 'query',
|
||||
fetchScalar = 'scalar',
|
||||
fetchSingle = 'single',
|
||||
insert = 'insert',
|
||||
execute = 'update',
|
||||
transaction = 'transaction',
|
||||
prepare = 'prepare'
|
||||
}
|
||||
|
||||
local alias_mt = {
|
||||
__index = function(self, key)
|
||||
if alias[key] then
|
||||
local method = MySQL[alias[key]]
|
||||
MySQL.Async[key] = method
|
||||
MySQL.Sync[key] = method.await
|
||||
alias[key] = nil
|
||||
return self[key]
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
local function addStore(query, cb)
|
||||
assert(type(query) == 'string', 'The SQL Query must be a string')
|
||||
|
||||
local storeN = #queryStore + 1
|
||||
queryStore[storeN] = query
|
||||
|
||||
return cb and cb(storeN) or storeN
|
||||
end
|
||||
|
||||
MySQL.Sync = setmetatable({ store = addStore }, alias_mt)
|
||||
MySQL.Async = setmetatable({ store = addStore }, alias_mt)
|
||||
|
||||
local function onReady(cb)
|
||||
while GetResourceState('oxmysql') ~= 'started' do
|
||||
Wait(50)
|
||||
end
|
||||
|
||||
oxmysql.awaitConnection()
|
||||
|
||||
return cb and cb() or true
|
||||
end
|
||||
|
||||
MySQL.ready = setmetatable({
|
||||
await = onReady
|
||||
}, {
|
||||
__call = function(_, cb)
|
||||
Citizen.CreateThreadNow(function() onReady(cb) end)
|
||||
end,
|
||||
})
|
||||
|
||||
function MySQL.startTransaction(cb)
|
||||
return oxmysql:startTransaction(cb, resourceName)
|
||||
end
|
||||
|
||||
_ENV.MySQL = MySQL
|
||||
@@ -0,0 +1,168 @@
|
||||
type Query = string | number;
|
||||
type Params = Record<string, unknown> | unknown[] | Function;
|
||||
type Callback<T> = (result: T | null) => void;
|
||||
|
||||
type Transaction =
|
||||
| string[]
|
||||
| [string, Params][]
|
||||
| { query: string; values: Params }[]
|
||||
| { query: string; parameters: Params }[];
|
||||
|
||||
interface Result {
|
||||
[column: string | number]: any;
|
||||
affectedRows?: number;
|
||||
fieldCount?: number;
|
||||
info?: string;
|
||||
insertId?: number;
|
||||
serverStatus?: number;
|
||||
warningStatus?: number;
|
||||
changedRows?: number;
|
||||
}
|
||||
|
||||
interface Row {
|
||||
[column: string | number]: unknown;
|
||||
}
|
||||
|
||||
interface OxMySQL {
|
||||
store: (query: string) => void;
|
||||
ready: (callback: () => void) => void;
|
||||
query: <T = Result | null>(query: Query, params?: Params | Callback<T>, cb?: Callback<T>) => Promise<T>;
|
||||
single: <T = Row | null>(
|
||||
query: Query,
|
||||
params?: Params | Callback<Exclude<T, []>>,
|
||||
cb?: Callback<Exclude<T, []>>
|
||||
) => Promise<Exclude<T, []>>;
|
||||
scalar: <T = unknown | null>(
|
||||
query: Query,
|
||||
params?: Params | Callback<Exclude<T, []>>,
|
||||
cb?: Callback<Exclude<T, []>>
|
||||
) => Promise<Exclude<T, []>>;
|
||||
update: <T = number | null>(query: Query, params?: Params | Callback<T>, cb?: Callback<T>) => Promise<T>;
|
||||
insert: <T = number | null>(query: Query, params?: Params | Callback<T>, cb?: Callback<T>) => Promise<T>;
|
||||
prepare: <T = any>(query: Query, params?: Params | Callback<T>, cb?: Callback<T>) => Promise<T>;
|
||||
rawExecute: <T = Result | null>(query: Query, params?: Params | Callback<T>, cb?: Callback<T>) => Promise<T>;
|
||||
transaction: (query: Transaction, params?: Params | Callback<boolean>, cb?: Callback<boolean>) => Promise<boolean>;
|
||||
isReady: () => boolean;
|
||||
awaitConnection: () => Promise<true>;
|
||||
startTransaction: (
|
||||
cb: (query: <T = Result | null>(statement: string, params?: Params) => Promise<T>) => Promise<boolean | void>
|
||||
) => Promise<boolean>;
|
||||
}
|
||||
|
||||
const QueryStore: string[] = [];
|
||||
|
||||
function assert(condition: boolean, message: string) {
|
||||
if (!condition) throw new TypeError(message);
|
||||
}
|
||||
|
||||
const safeArgs = (query: Query | Transaction, params?: any, cb?: Function, transaction?: true) => {
|
||||
if (typeof query === 'number') {
|
||||
query = QueryStore[query];
|
||||
assert(typeof query === 'string', 'First argument received invalid query store reference');
|
||||
}
|
||||
|
||||
if (transaction) {
|
||||
assert(typeof query === 'object', `First argument expected object, recieved ${typeof query}`);
|
||||
} else {
|
||||
assert(typeof query === 'string', `First argument expected string, received ${typeof query}`);
|
||||
}
|
||||
|
||||
if (params) {
|
||||
const paramType = typeof params;
|
||||
assert(
|
||||
paramType === 'object' || paramType === 'function',
|
||||
`Second argument expected object or function, received ${paramType}`
|
||||
);
|
||||
|
||||
if (!cb && paramType === 'function') {
|
||||
cb = params;
|
||||
params = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (cb !== undefined) assert(typeof cb === 'function', `Third argument expected function, received ${typeof cb}`);
|
||||
|
||||
return [query, params, cb];
|
||||
};
|
||||
|
||||
declare var global: any;
|
||||
const exp = global.exports.oxmysql;
|
||||
const currentResourceName = GetCurrentResourceName();
|
||||
|
||||
function execute(method: string, query: Query | Transaction, params?: Params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
exp[method](
|
||||
query,
|
||||
params,
|
||||
(result, error) => {
|
||||
if (error) return reject(error);
|
||||
resolve(result);
|
||||
},
|
||||
currentResourceName,
|
||||
true
|
||||
);
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export const oxmysql: OxMySQL = {
|
||||
store(query) {
|
||||
assert(typeof query !== 'string', `Query expects a string, received ${typeof query}`);
|
||||
|
||||
return QueryStore.push(query);
|
||||
},
|
||||
ready(callback) {
|
||||
setImmediate(async () => {
|
||||
while (GetResourceState('oxmysql') !== 'started') await new Promise((resolve) => setTimeout(resolve, 50, null));
|
||||
callback();
|
||||
});
|
||||
},
|
||||
async query(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('query', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async single(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('single', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async scalar(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('scalar', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async update(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('update', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async insert(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('insert', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async prepare(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('prepare', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async rawExecute(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb);
|
||||
const result = await execute('rawExecute', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
async transaction(query, params, cb) {
|
||||
[query, params, cb] = safeArgs(query, params, cb, true);
|
||||
const result = await execute('transaction', query, params);
|
||||
return cb ? cb(result) : result;
|
||||
},
|
||||
isReady() {
|
||||
return exp.isReady();
|
||||
},
|
||||
async awaitConnection() {
|
||||
return await exp.awaitConnection();
|
||||
},
|
||||
async startTransaction(cb) {
|
||||
return exp.startTransaction(cb, currentResourceName);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
# OxMySQL exports wrapper for FiveM
|
||||
|
||||
Types are fully supported and you will get intellisense on the `oxmysql` object when using it.
|
||||
|
||||
## Installation
|
||||
|
||||
```yaml
|
||||
# With pnpm
|
||||
pnpm add @overextended/oxmysql
|
||||
|
||||
# With Yarn
|
||||
yarn add @overextended/oxmysql
|
||||
|
||||
# With npm
|
||||
npm install @overextended/oxmysql
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Import as module:
|
||||
|
||||
```js
|
||||
import { oxmysql } from '@overextended/oxmysql';
|
||||
```
|
||||
|
||||
Import with require:
|
||||
|
||||
```js
|
||||
const { oxmysql } = require('@overextended/oxmysql');
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
[View documentation](https://overextended.github.io/docs/oxmysql)
|
||||
|
||||
```js
|
||||
oxmysql.scalar('SELECT username FROM users', (result) => {
|
||||
console.log(result)
|
||||
}).catch(console.error)
|
||||
|
||||
oxmysql.scalar('SELECT username FROM users').then((result) => {
|
||||
console.log(result)
|
||||
}).catch(console.error)
|
||||
|
||||
const result = await oxmysql.scalar('SELECT username FROM users').catch(console.error)
|
||||
console.log(result)
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
LGPL-3.0
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "@overextended/oxmysql",
|
||||
"version": "1.4.2",
|
||||
"description": "Exports wrapper for oxmysql",
|
||||
"types": "MySQL.d.ts",
|
||||
"main": "MySQL.js",
|
||||
"scripts": {
|
||||
"prepublish": "tsc"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/overextended/oxmysql.git"
|
||||
},
|
||||
"keywords": [
|
||||
"fivem",
|
||||
"oxmysql",
|
||||
"sql"
|
||||
],
|
||||
"author": "Overextended",
|
||||
"license": "LGPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/overextended/oxmysql/issues"
|
||||
},
|
||||
"homepage": "https://github.com/overextended/oxmysql#readme"
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"outDir": ".",
|
||||
"strict": true,
|
||||
"module": "CommonJS",
|
||||
"types": ["@citizenfx/server"],
|
||||
"declaration": true,
|
||||
"sourceMap": true,
|
||||
"target": "ESNext",
|
||||
"allowJs": true,
|
||||
"lib": ["ESNext"],
|
||||
"noEmitOnError": false,
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"rootDir": ".",
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": false,
|
||||
"noEmit": false
|
||||
},
|
||||
"include": ["MySQL.ts"],
|
||||
"exclude": ["**/node_modules"]
|
||||
}
|
||||
Reference in New Issue
Block a user