Functions available on both the server and the client, and the exports for scripts that do not use the `ObsiLib` object.

## Detection

```lua
ObsiLib.framework    -- 'esx' | 'qb' | 'qbx' | 'custom'
ObsiLib.inventory    -- 'ox_inventory' | 'qb-inventory' | ... | 'custom' | 'framework'
ObsiLib.version      -- '1.0.0'
ObsiLib.detect()     -- run detection again
```

## Utilities

```lua
ObsiLib.util.round(3.14159, 2)              -- 3.14
ObsiLib.util.percent(25, 200)               -- 12.5
ObsiLib.util.clamp(150, 0, 100)             -- 100
ObsiLib.util.trim('  text ')
ObsiLib.util.split('a,b,c', ',')
ObsiLib.util.randomString(8, 'ABC123')
ObsiLib.util.formatNumber(1250000)          -- '1 250 000'
ObsiLib.util.identifierValue('discord:123') -- '123'
ObsiLib.util.discordId(source)              -- server only
ObsiLib.util.identifiers(source)            -- server only, { license = 'license:..', discord = 'discord:..' }
```

## Locale and debugging

```lua
ObsiLib.locale('stash_title')                              -- Obsi Lib's own strings

ObsiLib.debug.print('warn', 'Something happened', { any = 'table' })
ObsiLib.debug.log('only printed with ObsiConfig.Debug')
ObsiLib.debug.dump(value)                                  -- pretty JSON string
```

## Exports

For scripts that do not use the object:

| Side | Exports |
| --- | --- |
| Both | `get` |
| Server | `notify`, `playSound`, `playSoundAt`, `stopSound`, `copsOnline`, `generatePlate`, `log`, `useItem` (ox_inventory item hook) |
| Client | `notify`, `progress`, `cancelProgress`, `progressActive`, `showText`, `hideText`, `textOpen`, `playSound`, `playSoundAt`, `stopSound` |

```lua
exports['obsi-lib']:notify({ title = 'Shop', description = 'Thanks for your purchase.', type = 'success' })
```
