nuxt-directus-sdk 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.mts +77 -0
- package/dist/module.d.ts +77 -0
- package/dist/module.json +9 -0
- package/dist/module.mjs +224 -0
- package/dist/runtime/composables/auth.d.ts +22 -0
- package/dist/runtime/composables/auth.mjs +83 -0
- package/dist/runtime/composables/directus.d.ts +2 -0
- package/dist/runtime/composables/directus.mjs +35 -0
- package/dist/runtime/composables/domain.d.ts +4 -0
- package/dist/runtime/composables/domain.mjs +11 -0
- package/dist/runtime/composables/files.d.ts +6 -0
- package/dist/runtime/composables/files.mjs +38 -0
- package/dist/runtime/composables/toast.d.ts +15 -0
- package/dist/runtime/composables/toast.mjs +41 -0
- package/dist/runtime/composables/tokens.d.ts +9 -0
- package/dist/runtime/composables/tokens.mjs +53 -0
- package/dist/runtime/oas/index.d.ts +5 -0
- package/dist/runtime/oas/index.mjs +100 -0
- package/dist/runtime/oas/types.d.ts +27 -0
- package/dist/runtime/oas/types.mjs +0 -0
- package/dist/runtime/plugin.client.d.ts +2 -0
- package/dist/runtime/plugin.client.mjs +8 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.mjs +35 -0
- package/dist/runtime/server/services/directus.d.ts +5 -0
- package/dist/runtime/server/services/directus.mjs +28 -0
- package/dist/runtime/server/services/index.d.ts +1 -0
- package/dist/runtime/server/services/index.mjs +1 -0
- package/dist/runtime/types/index.d.ts +38 -0
- package/dist/types.d.mts +15 -0
- package/dist/types.d.ts +15 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# directus-nuxt-sdk
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
[![License][license-src]][license-href]
|
|
6
|
+
[![Nuxt][nuxt-src]][nuxt-href]
|
|
7
|
+
|
|
8
|
+
> A bunch of directus helpers for nuxt applications
|
|
9
|
+
|
|
10
|
+
- [✨ Release Notes](/CHANGELOG.md)
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- ⛰ Built-in Directus auth and type generation
|
|
15
|
+
- 🚠 Built-in helpers and utils
|
|
16
|
+
|
|
17
|
+
## Quick Setup
|
|
18
|
+
|
|
19
|
+
1. Add `directus-nuxt-sdk` dependency to your project
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Using pnpm
|
|
23
|
+
pnpm add -D directus-nuxt-sdk
|
|
24
|
+
|
|
25
|
+
# Using yarn
|
|
26
|
+
yarn add --dev directus-nuxt-sdk
|
|
27
|
+
|
|
28
|
+
# Using npm
|
|
29
|
+
npm install --save-dev directus-nuxt-sdk
|
|
30
|
+
|
|
31
|
+
# Using bun
|
|
32
|
+
bun install --save-dev directus-nuxt-sdk
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
2. Add `directus-nuxt-sdk` to the `modules` section of `nuxt.config.ts`
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
export default defineNuxtConfig({
|
|
39
|
+
modules: [
|
|
40
|
+
'directus-nuxt-sdk'
|
|
41
|
+
]
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
That's it! You can now use Directus your Nuxt app ✨
|
|
46
|
+
|
|
47
|
+
## Development
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Install dependencies
|
|
51
|
+
npm install
|
|
52
|
+
|
|
53
|
+
# Generate type stubs
|
|
54
|
+
npm run dev:prepare
|
|
55
|
+
|
|
56
|
+
# Develop with the playground
|
|
57
|
+
npm run dev
|
|
58
|
+
|
|
59
|
+
# Build the playground
|
|
60
|
+
npm run dev:build
|
|
61
|
+
|
|
62
|
+
# Run ESLint
|
|
63
|
+
npm run lint
|
|
64
|
+
|
|
65
|
+
# Run Vitest
|
|
66
|
+
npm run test
|
|
67
|
+
npm run test:watch
|
|
68
|
+
|
|
69
|
+
# Release new version
|
|
70
|
+
npm run release
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
<!-- Badges -->
|
|
74
|
+
[npm-version-src]: https://img.shields.io/npm/v/directus-nuxt-sdk/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
75
|
+
[npm-version-href]: https://npmjs.com/package/directus-nuxt-sdk
|
|
76
|
+
|
|
77
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/directus-nuxt-sdk.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
78
|
+
[npm-downloads-href]: https://npmjs.com/package/directus-nuxt-sdk
|
|
79
|
+
|
|
80
|
+
[license-src]: https://img.shields.io/npm/l/directus-nuxt-sdk.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
81
|
+
[license-href]: https://npmjs.com/package/directus-nuxt-sdk
|
|
82
|
+
|
|
83
|
+
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
|
|
84
|
+
[nuxt-href]: https://nuxt.com
|
package/dist/module.cjs
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { Query } from '@directus/sdk';
|
|
3
|
+
import { DirectusCollections } from '#build/types/directus';
|
|
4
|
+
|
|
5
|
+
interface ModuleOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Directus API URL
|
|
8
|
+
* @default process.env.DIRECTUS_URL
|
|
9
|
+
* @type string
|
|
10
|
+
*/
|
|
11
|
+
url?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Admin Auth Token used for generating types and server functions
|
|
14
|
+
* @default process.env.DIRECTUS_ADMIN_TOKEN
|
|
15
|
+
* @type string
|
|
16
|
+
*/
|
|
17
|
+
adminToken?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Fetch the user serverside
|
|
20
|
+
*
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
fetchUser?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Directus Auth Options
|
|
26
|
+
* @default {}
|
|
27
|
+
* @type Query<DirectusCollections, 'directus_users'>
|
|
28
|
+
*/
|
|
29
|
+
fetchUserParams?: Query<DirectusCollections, 'directus_users'>;
|
|
30
|
+
/**
|
|
31
|
+
* Add Directus Admin in Nuxt Devtools
|
|
32
|
+
*
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
devtools?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Token Cookie Name
|
|
38
|
+
* @type string
|
|
39
|
+
* @ default 'directus_token'
|
|
40
|
+
*/
|
|
41
|
+
cookieNameToken?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Refresh Token Cookie Name
|
|
44
|
+
* @type string
|
|
45
|
+
* @default 'directus_refresh_token'
|
|
46
|
+
*/
|
|
47
|
+
cookieNameRefreshToken?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The max age for auth cookies in seconds.
|
|
50
|
+
* This should match your directus env key AUTH_TOKEN_TTL
|
|
51
|
+
* @type string
|
|
52
|
+
* @default 900
|
|
53
|
+
*/
|
|
54
|
+
cookieMaxAge?: number;
|
|
55
|
+
/**
|
|
56
|
+
* The max age for auth cookies in seconds.
|
|
57
|
+
* This should match your directus env key REFRESH_TOKEN_TTL
|
|
58
|
+
* @type string
|
|
59
|
+
* @default 604800
|
|
60
|
+
*/
|
|
61
|
+
cookieMaxAgeRefreshToken?: number;
|
|
62
|
+
/**
|
|
63
|
+
* The SameSite attribute for auth cookies.
|
|
64
|
+
* @type string
|
|
65
|
+
* @default 'lax'
|
|
66
|
+
*/
|
|
67
|
+
cookieSameSite?: 'strict' | 'lax' | 'none' | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* The Secure attribute for auth cookies.
|
|
70
|
+
* @type boolean
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
cookieSecure?: boolean;
|
|
74
|
+
}
|
|
75
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
|
|
76
|
+
|
|
77
|
+
export { type ModuleOptions, _default as default };
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
import { Query } from '@directus/sdk';
|
|
3
|
+
import { DirectusCollections } from '#build/types/directus';
|
|
4
|
+
|
|
5
|
+
interface ModuleOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Directus API URL
|
|
8
|
+
* @default process.env.DIRECTUS_URL
|
|
9
|
+
* @type string
|
|
10
|
+
*/
|
|
11
|
+
url?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Admin Auth Token used for generating types and server functions
|
|
14
|
+
* @default process.env.DIRECTUS_ADMIN_TOKEN
|
|
15
|
+
* @type string
|
|
16
|
+
*/
|
|
17
|
+
adminToken?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Fetch the user serverside
|
|
20
|
+
*
|
|
21
|
+
* @default true
|
|
22
|
+
*/
|
|
23
|
+
fetchUser?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Directus Auth Options
|
|
26
|
+
* @default {}
|
|
27
|
+
* @type Query<DirectusCollections, 'directus_users'>
|
|
28
|
+
*/
|
|
29
|
+
fetchUserParams?: Query<DirectusCollections, 'directus_users'>;
|
|
30
|
+
/**
|
|
31
|
+
* Add Directus Admin in Nuxt Devtools
|
|
32
|
+
*
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
devtools?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Token Cookie Name
|
|
38
|
+
* @type string
|
|
39
|
+
* @ default 'directus_token'
|
|
40
|
+
*/
|
|
41
|
+
cookieNameToken?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Refresh Token Cookie Name
|
|
44
|
+
* @type string
|
|
45
|
+
* @default 'directus_refresh_token'
|
|
46
|
+
*/
|
|
47
|
+
cookieNameRefreshToken?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The max age for auth cookies in seconds.
|
|
50
|
+
* This should match your directus env key AUTH_TOKEN_TTL
|
|
51
|
+
* @type string
|
|
52
|
+
* @default 900
|
|
53
|
+
*/
|
|
54
|
+
cookieMaxAge?: number;
|
|
55
|
+
/**
|
|
56
|
+
* The max age for auth cookies in seconds.
|
|
57
|
+
* This should match your directus env key REFRESH_TOKEN_TTL
|
|
58
|
+
* @type string
|
|
59
|
+
* @default 604800
|
|
60
|
+
*/
|
|
61
|
+
cookieMaxAgeRefreshToken?: number;
|
|
62
|
+
/**
|
|
63
|
+
* The SameSite attribute for auth cookies.
|
|
64
|
+
* @type string
|
|
65
|
+
* @default 'lax'
|
|
66
|
+
*/
|
|
67
|
+
cookieSameSite?: 'strict' | 'lax' | 'none' | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* The Secure attribute for auth cookies.
|
|
70
|
+
* @type boolean
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
cookieSecure?: boolean;
|
|
74
|
+
}
|
|
75
|
+
declare const _default: _nuxt_schema.NuxtModule<ModuleOptions>;
|
|
76
|
+
|
|
77
|
+
export { type ModuleOptions, _default as default };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { defu } from 'defu';
|
|
2
|
+
import { defineNuxtModule, createResolver, addPlugin, addImportsDir, addComponentsDir, addTypeTemplate, logger } from '@nuxt/kit';
|
|
3
|
+
import { joinURL } from 'ufo';
|
|
4
|
+
import { snakeCase } from 'change-case';
|
|
5
|
+
import { createDirectus, authentication, rest, readOpenApiSpec } from '@directus/sdk';
|
|
6
|
+
|
|
7
|
+
const name = "nuxt-directus-sdk";
|
|
8
|
+
const version = "0.0.2";
|
|
9
|
+
|
|
10
|
+
function mapPropertyType(propertyType) {
|
|
11
|
+
return propertyType === "integer" ? "number" : propertyType;
|
|
12
|
+
}
|
|
13
|
+
function processOneOfProperty(schemas, name, property) {
|
|
14
|
+
const ref = property.oneOf.find((item) => {
|
|
15
|
+
return "$ref" in item;
|
|
16
|
+
});
|
|
17
|
+
if (ref) {
|
|
18
|
+
const $ref = ref.$ref;
|
|
19
|
+
const $refKey = $ref.split("/").pop();
|
|
20
|
+
if ($refKey) {
|
|
21
|
+
const $refSchema = `DirectusCollections['${schemas[$refKey]?.["x-collection"]}']`;
|
|
22
|
+
if ($refSchema)
|
|
23
|
+
return $refSchema;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const firstValue = property.oneOf?.[0];
|
|
27
|
+
if ("type" in firstValue) {
|
|
28
|
+
const firstType = mapPropertyType(firstValue.type);
|
|
29
|
+
if (firstType)
|
|
30
|
+
return firstType;
|
|
31
|
+
}
|
|
32
|
+
console.error("Unknown schema for oneOf", name, property);
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
function processProperty(schemas, name, property) {
|
|
36
|
+
if ("type" in property) {
|
|
37
|
+
if (property.type === "array" && property.items) {
|
|
38
|
+
if (!property.items.oneOf)
|
|
39
|
+
return processProperty(schemas, name, property.items);
|
|
40
|
+
return `
|
|
41
|
+
"${name}": ${processOneOfProperty(schemas, name, property.items)};
|
|
42
|
+
`;
|
|
43
|
+
} else {
|
|
44
|
+
return `
|
|
45
|
+
${property.format ? `/* ${property.format} */` : ""}
|
|
46
|
+
"${name}": ${mapPropertyType(property.type ?? "string")};
|
|
47
|
+
`;
|
|
48
|
+
}
|
|
49
|
+
} else if ("oneOf" in property) {
|
|
50
|
+
const value = processOneOfProperty(schemas, name, property);
|
|
51
|
+
if (!value)
|
|
52
|
+
return;
|
|
53
|
+
const simpleTypes = ["string", "number", "boolean"];
|
|
54
|
+
const valueType = simpleTypes.includes(value) ? value : `Single<${value}>`;
|
|
55
|
+
return `
|
|
56
|
+
"${name}": ${valueType};
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function generateTypes(options) {
|
|
61
|
+
const directus = createDirectus(options.url).with(authentication("json", { autoRefresh: false })).with(rest());
|
|
62
|
+
directus.setToken(options.token);
|
|
63
|
+
const data = await directus.request(readOpenApiSpec());
|
|
64
|
+
const types = [];
|
|
65
|
+
const schemas = data.components.schemas;
|
|
66
|
+
const schemaNames = [];
|
|
67
|
+
Object.entries(schemas).forEach(([_, schema]) => {
|
|
68
|
+
const schemaName = schema["x-collection"];
|
|
69
|
+
if (!schemaName)
|
|
70
|
+
return;
|
|
71
|
+
if (schema.type !== "object") {
|
|
72
|
+
console.error(schemaName, "is not an object");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (schemaNames.includes(schemaName))
|
|
76
|
+
return;
|
|
77
|
+
schemaNames.push(schemaName);
|
|
78
|
+
const properties = [];
|
|
79
|
+
Object.entries(schema.properties).forEach(([name, property]) => {
|
|
80
|
+
const propertyType = processProperty(schemas, name, property);
|
|
81
|
+
if (propertyType)
|
|
82
|
+
properties.push(propertyType.trim());
|
|
83
|
+
});
|
|
84
|
+
types.push(`${snakeCase(schemaName)}: {
|
|
85
|
+
${properties.join("\n")}
|
|
86
|
+
}[];
|
|
87
|
+
`);
|
|
88
|
+
});
|
|
89
|
+
const exportProperties = types.join("\n");
|
|
90
|
+
return `
|
|
91
|
+
export type Single<T extends any[]> = T extends (infer U)[] ? U : never;
|
|
92
|
+
|
|
93
|
+
export type DirectusCollections = {
|
|
94
|
+
${exportProperties}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
export type DirectusCollectionUser = Single<DirectusCollections['directus_users']>;
|
|
98
|
+
|
|
99
|
+
declare global {
|
|
100
|
+
type Single = Single
|
|
101
|
+
type DirectusCollections = DirectusCollections
|
|
102
|
+
type DirectusCollectionUser = DirectusCollectionUser
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export {};
|
|
106
|
+
`;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const configKey = "rolley";
|
|
110
|
+
const module = defineNuxtModule({
|
|
111
|
+
meta: {
|
|
112
|
+
name,
|
|
113
|
+
version,
|
|
114
|
+
configKey,
|
|
115
|
+
compatibility: {
|
|
116
|
+
nuxt: "^3.0.0",
|
|
117
|
+
bridge: false
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
defaults: {
|
|
121
|
+
url: process.env.DIRECTUS_URL,
|
|
122
|
+
adminToken: process.env.DIRECTUS_ADMIN_TOKEN,
|
|
123
|
+
fetchUser: true,
|
|
124
|
+
devtools: false,
|
|
125
|
+
cookieNameToken: "directus_token",
|
|
126
|
+
cookieNameRefreshToken: "directus_refresh_token",
|
|
127
|
+
// Nuxt Cookies Docs @ https://nuxt.com/docs/api/composables/use-cookie
|
|
128
|
+
cookieMaxAge: 900,
|
|
129
|
+
cookieMaxAgeRefreshToken: 604800,
|
|
130
|
+
cookieSameSite: "lax",
|
|
131
|
+
cookieSecure: false
|
|
132
|
+
},
|
|
133
|
+
async setup(options, nuxt) {
|
|
134
|
+
nuxt.options.runtimeConfig.public = nuxt.options.runtimeConfig.public || {};
|
|
135
|
+
nuxt.options.runtimeConfig.public[configKey] = defu(nuxt.options.runtimeConfig.public[configKey], {
|
|
136
|
+
url: options.url,
|
|
137
|
+
fetchUser: options.fetchUser,
|
|
138
|
+
fetchUserParams: options.fetchUserParams,
|
|
139
|
+
devtools: options.devtools,
|
|
140
|
+
cookieNameToken: options.cookieNameToken,
|
|
141
|
+
cookieNameRefreshToken: options.cookieNameRefreshToken,
|
|
142
|
+
cookieMaxAge: options.cookieMaxAge,
|
|
143
|
+
cookieMaxAgeRefreshToken: options.cookieMaxAgeRefreshToken,
|
|
144
|
+
cookieSameSite: options.cookieSameSite,
|
|
145
|
+
cookieSecure: options.cookieSecure
|
|
146
|
+
});
|
|
147
|
+
const resolver = createResolver(import.meta.url);
|
|
148
|
+
addPlugin(resolver.resolve("./runtime/plugin"));
|
|
149
|
+
addPlugin({
|
|
150
|
+
src: resolver.resolve("./runtime/plugin.client"),
|
|
151
|
+
mode: "client"
|
|
152
|
+
});
|
|
153
|
+
addImportsDir(resolver.resolve("./runtime/composables"));
|
|
154
|
+
addComponentsDir({
|
|
155
|
+
path: resolver.resolve("./runtime/components"),
|
|
156
|
+
pathPrefix: false,
|
|
157
|
+
prefix: "",
|
|
158
|
+
global: true
|
|
159
|
+
});
|
|
160
|
+
nuxt.options.css.push("vue-toastification/dist/index.css");
|
|
161
|
+
nuxt.options.build.transpile.push("vue-toastification");
|
|
162
|
+
nuxt.hook("nitro:config", (nitroConfig) => {
|
|
163
|
+
nitroConfig.alias = nitroConfig.alias || {};
|
|
164
|
+
nitroConfig.externals = defu(typeof nitroConfig.externals === "object" ? nitroConfig.externals : {}, {
|
|
165
|
+
inline: [resolver.resolve("./runtime")]
|
|
166
|
+
});
|
|
167
|
+
nitroConfig.alias[`#${configKey}`] = resolver.resolve("./runtime/server/services");
|
|
168
|
+
});
|
|
169
|
+
addTypeTemplate({
|
|
170
|
+
filename: `types/${configKey}.d.ts`,
|
|
171
|
+
getContents: () => [
|
|
172
|
+
`declare module '#${configKey}' {`,
|
|
173
|
+
` const useDirectus: typeof import('${resolver.resolve("./runtime/server/services")}').useDirectus`,
|
|
174
|
+
` const useAdminDirectus: typeof import('${resolver.resolve("./runtime/server/services")}').useAdminDirectus`,
|
|
175
|
+
` const useDirectusUrl: typeof import('${resolver.resolve("./runtime/server/services")}').useDirectusUrl`,
|
|
176
|
+
` const useDirectusAccessToken: typeof import('${resolver.resolve("./runtime/server/services")}').useDirectusAccessToken`,
|
|
177
|
+
"}"
|
|
178
|
+
].join("\n")
|
|
179
|
+
});
|
|
180
|
+
nuxt.hook("prepare:types", (options2) => {
|
|
181
|
+
options2.references.push({ path: resolver.resolve(nuxt.options.buildDir, `types/${configKey}.d.ts`) });
|
|
182
|
+
});
|
|
183
|
+
if (options.url) {
|
|
184
|
+
const adminUrl = joinURL(options.url, "/admin/");
|
|
185
|
+
logger.info(`Directus Admin URL: ${adminUrl}`);
|
|
186
|
+
if (options.devtools) {
|
|
187
|
+
nuxt.hook("devtools:customTabs", (iframeTabs) => {
|
|
188
|
+
iframeTabs.push({
|
|
189
|
+
name: "directus",
|
|
190
|
+
title: "Directus",
|
|
191
|
+
icon: "simple-icons:directus",
|
|
192
|
+
view: {
|
|
193
|
+
type: "iframe",
|
|
194
|
+
src: adminUrl
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (options.adminToken) {
|
|
200
|
+
logger.info("Generating Directus types");
|
|
201
|
+
try {
|
|
202
|
+
const typesPath = addTypeTemplate({
|
|
203
|
+
filename: "types/directus.d.ts",
|
|
204
|
+
getContents() {
|
|
205
|
+
return generateTypes({
|
|
206
|
+
url: options.url ?? "",
|
|
207
|
+
token: options.adminToken ?? ""
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}).dst;
|
|
211
|
+
nuxt.hook("prepare:types", (options2) => {
|
|
212
|
+
options2.references.push({ path: typesPath });
|
|
213
|
+
});
|
|
214
|
+
} catch (error) {
|
|
215
|
+
logger.error(error.message);
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
logger.info("Add DIRECTUS_ADMIN_TOKEN to the .env file to generate directus types");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
export { module as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ComputedRef, Ref } from '#imports';
|
|
2
|
+
import type { DirectusCollectionUser } from '#build/types/directus';
|
|
3
|
+
export declare function useDirectusUser(): Ref<any>;
|
|
4
|
+
export interface DirectusAuth {
|
|
5
|
+
user: Ref<DirectusCollectionUser | null>;
|
|
6
|
+
loggedIn: ComputedRef<boolean>;
|
|
7
|
+
refreshTokens(): Promise<void>;
|
|
8
|
+
fetchUser(): Promise<DirectusCollectionUser | null>;
|
|
9
|
+
updateUser(data: Partial<DirectusCollectionUser>): Promise<DirectusCollectionUser | null>;
|
|
10
|
+
login(email: string, password: string): Promise<{
|
|
11
|
+
user: DirectusCollectionUser | null;
|
|
12
|
+
access_token: string;
|
|
13
|
+
refreshToken: string | null;
|
|
14
|
+
expires: number;
|
|
15
|
+
redirect(defaultPath?: string): void;
|
|
16
|
+
}>;
|
|
17
|
+
logout(): Promise<void>;
|
|
18
|
+
register(data: Partial<DirectusCollectionUser>): Promise<DirectusCollectionUser>;
|
|
19
|
+
requestPasswordReset(email: string, resetUrl?: string | null | undefined): Promise<void>;
|
|
20
|
+
resetPassword(token: string, password: string): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare function useDirectusAuth(): DirectusAuth;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createUser, passwordRequest, passwordReset, readMe, updateMe } from "@directus/sdk";
|
|
2
|
+
import { useDirectus } from "./directus.mjs";
|
|
3
|
+
import { useDirectusTokens } from "./tokens.mjs";
|
|
4
|
+
import { computed, useState } from "#imports";
|
|
5
|
+
import { useRouter, useRuntimeConfig } from "#app";
|
|
6
|
+
export function useDirectusUser() {
|
|
7
|
+
return useState("directus.user", () => null);
|
|
8
|
+
}
|
|
9
|
+
export function useDirectusAuth() {
|
|
10
|
+
const config = useRuntimeConfig();
|
|
11
|
+
const directus = useDirectus();
|
|
12
|
+
const tokens = useDirectusTokens();
|
|
13
|
+
const user = useDirectusUser();
|
|
14
|
+
const loggedIn = computed(() => user.value !== null);
|
|
15
|
+
async function fetchUser() {
|
|
16
|
+
try {
|
|
17
|
+
if (!tokens.refreshToken.value)
|
|
18
|
+
throw new Error("No refresh token");
|
|
19
|
+
await directus.refresh();
|
|
20
|
+
user.value = await directus.request(readMe(config.public.rolley.fetchUserParams));
|
|
21
|
+
} catch (e) {
|
|
22
|
+
user.value = null;
|
|
23
|
+
}
|
|
24
|
+
return user.value;
|
|
25
|
+
}
|
|
26
|
+
async function updateUser(data) {
|
|
27
|
+
const currentUser = user.value;
|
|
28
|
+
if (!currentUser?.id)
|
|
29
|
+
throw new Error("No user available");
|
|
30
|
+
user.value = await directus.request(updateMe(data, config.public.rolley.fetchUserParams));
|
|
31
|
+
return user.value;
|
|
32
|
+
}
|
|
33
|
+
async function login(email, password, options = {}) {
|
|
34
|
+
const response = await directus.login(email, password, options);
|
|
35
|
+
if (!response.access_token)
|
|
36
|
+
throw new Error("Login failed, please check your credentials.");
|
|
37
|
+
await fetchUser();
|
|
38
|
+
return {
|
|
39
|
+
user: user.value,
|
|
40
|
+
accessToken: response.access_token,
|
|
41
|
+
refreshToken: response.refresh_token,
|
|
42
|
+
expires: response.expires,
|
|
43
|
+
expiresAt: response.expires_at,
|
|
44
|
+
// Allow redirecting to a specific page after login
|
|
45
|
+
redirect(defaultPath = "/") {
|
|
46
|
+
const router = useRouter();
|
|
47
|
+
const route = router.currentRoute.value;
|
|
48
|
+
router.replace({ path: route.query.redirect ? decodeURIComponent(route.query.redirect) : defaultPath });
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function register(data) {
|
|
53
|
+
return directus.request(createUser(data));
|
|
54
|
+
}
|
|
55
|
+
async function requestPasswordReset(email, resetUrl) {
|
|
56
|
+
directus.request(passwordRequest(email, resetUrl));
|
|
57
|
+
}
|
|
58
|
+
async function resetPassword(token, password) {
|
|
59
|
+
directus.request(passwordReset(token, password));
|
|
60
|
+
}
|
|
61
|
+
async function logout() {
|
|
62
|
+
try {
|
|
63
|
+
await directus.logout();
|
|
64
|
+
} finally {
|
|
65
|
+
user.value = null;
|
|
66
|
+
tokens.refreshToken.value = null;
|
|
67
|
+
tokens.accessToken.value = null;
|
|
68
|
+
tokens.expires.value = null;
|
|
69
|
+
tokens.expiresAt.value = null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
user,
|
|
74
|
+
loggedIn,
|
|
75
|
+
fetchUser,
|
|
76
|
+
updateUser,
|
|
77
|
+
register,
|
|
78
|
+
login,
|
|
79
|
+
logout,
|
|
80
|
+
requestPasswordReset,
|
|
81
|
+
resetPassword
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare function useDirectusUrl(): string;
|
|
2
|
+
export declare function useDirectus(token?: string): import("@directus/sdk/dist/client-e8d6bf91").D<DirectusCollections> & import("@directus/sdk/dist/login-0506af09").d<DirectusCollections> & import("@directus/sdk/dist/login-0506af09").f<DirectusCollections> & import("@directus/sdk/dist/output-35b496cf").d<DirectusCollections>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { authentication, createDirectus, realtime, rest } from "@directus/sdk";
|
|
2
|
+
import { useDirectusTokens } from "./tokens.mjs";
|
|
3
|
+
import { useRuntimeConfig } from "#app";
|
|
4
|
+
export function useDirectusUrl() {
|
|
5
|
+
return useRuntimeConfig().public.rolley.url;
|
|
6
|
+
}
|
|
7
|
+
function createDirectusStorage() {
|
|
8
|
+
const tokens = useDirectusTokens();
|
|
9
|
+
return {
|
|
10
|
+
get() {
|
|
11
|
+
return {
|
|
12
|
+
access_token: tokens.accessToken.value,
|
|
13
|
+
refresh_token: tokens.refreshToken.value,
|
|
14
|
+
expires: tokens.expires.value,
|
|
15
|
+
expires_at: tokens.expiresAt.value
|
|
16
|
+
};
|
|
17
|
+
},
|
|
18
|
+
set(value) {
|
|
19
|
+
tokens.accessToken.value = value?.access_token ?? null;
|
|
20
|
+
tokens.refreshToken.value = value?.refresh_token ?? null;
|
|
21
|
+
tokens.expires.value = value?.expires ?? null;
|
|
22
|
+
tokens.expiresAt.value = value?.expires_at ?? null;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function useDirectus(token) {
|
|
27
|
+
const url = useDirectusUrl();
|
|
28
|
+
const directus = createDirectus(url).with(authentication("json", {
|
|
29
|
+
storage: createDirectusStorage(),
|
|
30
|
+
autoRefresh: token !== ""
|
|
31
|
+
})).with(rest()).with(realtime());
|
|
32
|
+
if (token)
|
|
33
|
+
directus.setToken(token);
|
|
34
|
+
return directus;
|
|
35
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { useState } from "#imports";
|
|
2
|
+
export function useDomain() {
|
|
3
|
+
return useState("domain", () => "");
|
|
4
|
+
}
|
|
5
|
+
export function useSubdomain() {
|
|
6
|
+
return useState("subdomain", () => "");
|
|
7
|
+
}
|
|
8
|
+
export function getSubdomainLink(slug) {
|
|
9
|
+
const domain = useDomain();
|
|
10
|
+
return `//${slug}.${domain.value}/`;
|
|
11
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DirectusThumbnailOptions } from '../types';
|
|
2
|
+
export declare function uploadDirectusFile(file: File, folder?: string): Promise<Record<string, any>>;
|
|
3
|
+
export declare function getDirectusAssetUrl(fileId: string, options?: {
|
|
4
|
+
token?: string;
|
|
5
|
+
}): string;
|
|
6
|
+
export declare function getDirectusThumbnailUrl(fileId: string, options?: DirectusThumbnailOptions): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { uploadFiles } from "@directus/sdk";
|
|
2
|
+
import { useDirectus, useDirectusUrl } from "./directus.mjs";
|
|
3
|
+
export async function uploadDirectusFile(file, folder) {
|
|
4
|
+
const directus = useDirectus();
|
|
5
|
+
const formData = new FormData();
|
|
6
|
+
formData.set("file", file);
|
|
7
|
+
if (folder)
|
|
8
|
+
formData.set("folder", folder);
|
|
9
|
+
return directus.request(uploadFiles(formData));
|
|
10
|
+
}
|
|
11
|
+
export function getDirectusAssetUrl(fileId, options) {
|
|
12
|
+
const directusUrl = useDirectusUrl();
|
|
13
|
+
const url = new URL(`${directusUrl}assets/${fileId}`);
|
|
14
|
+
if (options?.token)
|
|
15
|
+
url.searchParams.append("access_token", options.token);
|
|
16
|
+
return url.href;
|
|
17
|
+
}
|
|
18
|
+
export function getDirectusThumbnailUrl(fileId, options) {
|
|
19
|
+
const directusUrl = useDirectusUrl();
|
|
20
|
+
const url = new URL(`${directusUrl}assets/${fileId}`);
|
|
21
|
+
if (options) {
|
|
22
|
+
if (options.width)
|
|
23
|
+
url.searchParams.append("width", options.width.toFixed(0));
|
|
24
|
+
if (options.height)
|
|
25
|
+
url.searchParams.append("height", options.height.toFixed(0));
|
|
26
|
+
if (options.quality)
|
|
27
|
+
url.searchParams.append("quality", options.quality.toFixed(0));
|
|
28
|
+
if (options.withoutEnlargement)
|
|
29
|
+
url.searchParams.append("withoutEnlargement", "true");
|
|
30
|
+
if (options.fit)
|
|
31
|
+
url.searchParams.append("fit", options.fit);
|
|
32
|
+
if (options.format)
|
|
33
|
+
url.searchParams.append("format", options.format);
|
|
34
|
+
if (options.token)
|
|
35
|
+
url.searchParams.append("access_token", options.token);
|
|
36
|
+
}
|
|
37
|
+
return url.href;
|
|
38
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare function useToast(): {
|
|
2
|
+
log: (message: string) => Promise<void>;
|
|
3
|
+
success: (message: string, options?: (import("vue-toastification/dist/types/types").ToastOptions & {
|
|
4
|
+
type?: import("vue-toastification").TYPE.SUCCESS | undefined;
|
|
5
|
+
}) | undefined) => Promise<void>;
|
|
6
|
+
info: (message: string, options?: (import("vue-toastification/dist/types/types").ToastOptions & {
|
|
7
|
+
type?: import("vue-toastification").TYPE.INFO | undefined;
|
|
8
|
+
}) | undefined) => Promise<void>;
|
|
9
|
+
warn: (message: string, options?: (import("vue-toastification/dist/types/types").ToastOptions & {
|
|
10
|
+
type?: import("vue-toastification").TYPE.WARNING | undefined;
|
|
11
|
+
}) | undefined) => Promise<void>;
|
|
12
|
+
error: (message?: string, options?: (import("vue-toastification/dist/types/types").ToastOptions & {
|
|
13
|
+
type?: import("vue-toastification").TYPE.ERROR | undefined;
|
|
14
|
+
}) | undefined) => Promise<void>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useToast as useToastFn } from "vue-toastification";
|
|
2
|
+
export function useToast() {
|
|
3
|
+
const toast = useToastFn();
|
|
4
|
+
async function log(message) {
|
|
5
|
+
if (process.client)
|
|
6
|
+
toast(message);
|
|
7
|
+
else
|
|
8
|
+
console.log(message);
|
|
9
|
+
}
|
|
10
|
+
async function success(message, options) {
|
|
11
|
+
if (process.client)
|
|
12
|
+
toast.success(message, options);
|
|
13
|
+
else
|
|
14
|
+
console.log("success", message);
|
|
15
|
+
}
|
|
16
|
+
async function info(message, options) {
|
|
17
|
+
if (process.client)
|
|
18
|
+
toast.info(message, options);
|
|
19
|
+
else
|
|
20
|
+
console.info(message);
|
|
21
|
+
}
|
|
22
|
+
async function warn(message, options) {
|
|
23
|
+
if (process.client)
|
|
24
|
+
toast.warning(message, options);
|
|
25
|
+
else
|
|
26
|
+
console.warn(message);
|
|
27
|
+
}
|
|
28
|
+
async function error(message = "Something has gone wrong, please try again later.", options) {
|
|
29
|
+
if (process.client)
|
|
30
|
+
toast.error(message, options);
|
|
31
|
+
else
|
|
32
|
+
console.error(message);
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
log,
|
|
36
|
+
success,
|
|
37
|
+
info,
|
|
38
|
+
warn,
|
|
39
|
+
error
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CookieRef } from '#app';
|
|
2
|
+
export declare function getCookieDomain(): string | undefined;
|
|
3
|
+
export interface DirectusTokens {
|
|
4
|
+
accessToken: CookieRef<string | null>;
|
|
5
|
+
refreshToken: CookieRef<string | null>;
|
|
6
|
+
expires: CookieRef<number | null>;
|
|
7
|
+
expiresAt: CookieRef<number | null>;
|
|
8
|
+
}
|
|
9
|
+
export declare function useDirectusTokens(): DirectusTokens;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useDomain } from "./domain.mjs";
|
|
2
|
+
import { useCookie, useNuxtApp, useRuntimeConfig } from "#app";
|
|
3
|
+
export function getCookieDomain() {
|
|
4
|
+
const domain = useDomain();
|
|
5
|
+
return !domain.value.includes("localhost") ? `.${domain.value}` : void 0;
|
|
6
|
+
}
|
|
7
|
+
function directusCookie(name, cookieOptions) {
|
|
8
|
+
const nuxtApp = useNuxtApp();
|
|
9
|
+
nuxtApp._cookies = nuxtApp._cookies || {};
|
|
10
|
+
if (nuxtApp._cookies[name])
|
|
11
|
+
return nuxtApp._cookies[name];
|
|
12
|
+
const cookie = useCookie(name, cookieOptions);
|
|
13
|
+
nuxtApp._cookies[name] = cookie;
|
|
14
|
+
return cookie;
|
|
15
|
+
}
|
|
16
|
+
export function useDirectusTokens() {
|
|
17
|
+
const config = useRuntimeConfig().public.rolley;
|
|
18
|
+
const sharedOptions = {
|
|
19
|
+
sameSite: config.cookieSameSite,
|
|
20
|
+
secure: config.cookieSecure,
|
|
21
|
+
domain: getCookieDomain()
|
|
22
|
+
};
|
|
23
|
+
function accessToken() {
|
|
24
|
+
return directusCookie(config.cookieNameToken, {
|
|
25
|
+
...sharedOptions,
|
|
26
|
+
maxAge: config.cookieMaxAge
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function refreshToken() {
|
|
30
|
+
return directusCookie(config.cookieNameRefreshToken, {
|
|
31
|
+
...sharedOptions,
|
|
32
|
+
maxAge: config.cookieMaxAgeRefreshToken
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function expires() {
|
|
36
|
+
return directusCookie("directus_access_expires", {
|
|
37
|
+
...sharedOptions,
|
|
38
|
+
maxAge: config.cookieMaxAge
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function expiresAt() {
|
|
42
|
+
return directusCookie("directus_access_expires_at", {
|
|
43
|
+
...sharedOptions,
|
|
44
|
+
maxAge: config.cookieMaxAge
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
accessToken: accessToken(),
|
|
49
|
+
refreshToken: refreshToken(),
|
|
50
|
+
expires: expires(),
|
|
51
|
+
expiresAt: expiresAt()
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { GenerateTypeOptions, SchemaProperty, SchemaPropertyOneOf, SchemaPropertyType, SchemasRecord } from './types';
|
|
2
|
+
export declare function mapPropertyType(propertyType: SchemaPropertyType): "string" | "boolean" | "array" | "number";
|
|
3
|
+
export declare function processOneOfProperty(schemas: SchemasRecord, name: string, property: SchemaPropertyOneOf): string | undefined;
|
|
4
|
+
export declare function processProperty(schemas: SchemasRecord, name: string, property: SchemaProperty): string | undefined;
|
|
5
|
+
export declare function generateTypes(options: GenerateTypeOptions): Promise<string>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { snakeCase } from "change-case";
|
|
2
|
+
import { authentication, createDirectus, readOpenApiSpec, rest } from "@directus/sdk";
|
|
3
|
+
export function mapPropertyType(propertyType) {
|
|
4
|
+
return propertyType === "integer" ? "number" : propertyType;
|
|
5
|
+
}
|
|
6
|
+
export function processOneOfProperty(schemas, name, property) {
|
|
7
|
+
const ref = property.oneOf.find((item) => {
|
|
8
|
+
return "$ref" in item;
|
|
9
|
+
});
|
|
10
|
+
if (ref) {
|
|
11
|
+
const $ref = ref.$ref;
|
|
12
|
+
const $refKey = $ref.split("/").pop();
|
|
13
|
+
if ($refKey) {
|
|
14
|
+
const $refSchema = `DirectusCollections['${schemas[$refKey]?.["x-collection"]}']`;
|
|
15
|
+
if ($refSchema)
|
|
16
|
+
return $refSchema;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const firstValue = property.oneOf?.[0];
|
|
20
|
+
if ("type" in firstValue) {
|
|
21
|
+
const firstType = mapPropertyType(firstValue.type);
|
|
22
|
+
if (firstType)
|
|
23
|
+
return firstType;
|
|
24
|
+
}
|
|
25
|
+
console.error("Unknown schema for oneOf", name, property);
|
|
26
|
+
return "";
|
|
27
|
+
}
|
|
28
|
+
export function processProperty(schemas, name, property) {
|
|
29
|
+
if ("type" in property) {
|
|
30
|
+
if (property.type === "array" && property.items) {
|
|
31
|
+
if (!property.items.oneOf)
|
|
32
|
+
return processProperty(schemas, name, property.items);
|
|
33
|
+
return `
|
|
34
|
+
"${name}": ${processOneOfProperty(schemas, name, property.items)};
|
|
35
|
+
`;
|
|
36
|
+
} else {
|
|
37
|
+
return `
|
|
38
|
+
${property.format ? `/* ${property.format} */` : ""}
|
|
39
|
+
"${name}": ${mapPropertyType(property.type ?? "string")};
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
} else if ("oneOf" in property) {
|
|
43
|
+
const value = processOneOfProperty(schemas, name, property);
|
|
44
|
+
if (!value)
|
|
45
|
+
return;
|
|
46
|
+
const simpleTypes = ["string", "number", "boolean"];
|
|
47
|
+
const valueType = simpleTypes.includes(value) ? value : `Single<${value}>`;
|
|
48
|
+
return `
|
|
49
|
+
"${name}": ${valueType};
|
|
50
|
+
`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export async function generateTypes(options) {
|
|
54
|
+
const directus = createDirectus(options.url).with(authentication("json", { autoRefresh: false })).with(rest());
|
|
55
|
+
directus.setToken(options.token);
|
|
56
|
+
const data = await directus.request(readOpenApiSpec());
|
|
57
|
+
const types = [];
|
|
58
|
+
const schemas = data.components.schemas;
|
|
59
|
+
const schemaNames = [];
|
|
60
|
+
Object.entries(schemas).forEach(([_, schema]) => {
|
|
61
|
+
const schemaName = schema["x-collection"];
|
|
62
|
+
if (!schemaName)
|
|
63
|
+
return;
|
|
64
|
+
if (schema.type !== "object") {
|
|
65
|
+
console.error(schemaName, "is not an object");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (schemaNames.includes(schemaName))
|
|
69
|
+
return;
|
|
70
|
+
schemaNames.push(schemaName);
|
|
71
|
+
const properties = [];
|
|
72
|
+
Object.entries(schema.properties).forEach(([name, property]) => {
|
|
73
|
+
const propertyType = processProperty(schemas, name, property);
|
|
74
|
+
if (propertyType)
|
|
75
|
+
properties.push(propertyType.trim());
|
|
76
|
+
});
|
|
77
|
+
types.push(`${snakeCase(schemaName)}: {
|
|
78
|
+
${properties.join("\n")}
|
|
79
|
+
}[];
|
|
80
|
+
`);
|
|
81
|
+
});
|
|
82
|
+
const exportProperties = types.join("\n");
|
|
83
|
+
return `
|
|
84
|
+
export type Single<T extends any[]> = T extends (infer U)[] ? U : never;
|
|
85
|
+
|
|
86
|
+
export type DirectusCollections = {
|
|
87
|
+
${exportProperties}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export type DirectusCollectionUser = Single<DirectusCollections['directus_users']>;
|
|
91
|
+
|
|
92
|
+
declare global {
|
|
93
|
+
type Single = Single
|
|
94
|
+
type DirectusCollections = DirectusCollections
|
|
95
|
+
type DirectusCollectionUser = DirectusCollectionUser
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export {};
|
|
99
|
+
`;
|
|
100
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface GenerateTypeOptions {
|
|
2
|
+
url: string;
|
|
3
|
+
token: string;
|
|
4
|
+
collections?: string[];
|
|
5
|
+
}
|
|
6
|
+
export type SchemaPropertyType = 'string' | 'integer' | 'boolean' | 'array';
|
|
7
|
+
export interface SchemaPropertyOneOfReference {
|
|
8
|
+
$ref: string;
|
|
9
|
+
}
|
|
10
|
+
export type SchemaPropertyOneOfValue = SchemaPropertyOneOfReference | SchemaPropertySingle[];
|
|
11
|
+
export interface SchemaPropertyOneOf {
|
|
12
|
+
nullable: boolean;
|
|
13
|
+
oneOf: SchemaPropertyOneOfValue[];
|
|
14
|
+
}
|
|
15
|
+
export interface SchemaPropertySingle {
|
|
16
|
+
nullable: boolean;
|
|
17
|
+
type?: SchemaPropertyType;
|
|
18
|
+
format?: string;
|
|
19
|
+
items?: SchemaPropertyOneOf;
|
|
20
|
+
}
|
|
21
|
+
export type SchemaProperty = SchemaPropertySingle | SchemaPropertyOneOf;
|
|
22
|
+
export interface Schema {
|
|
23
|
+
type: string;
|
|
24
|
+
'x-collection'?: string;
|
|
25
|
+
properties: Record<string, SchemaProperty>;
|
|
26
|
+
}
|
|
27
|
+
export type SchemasRecord = Record<string, Schema>;
|
|
File without changes
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { fromUrl, parseDomain } from "parse-domain";
|
|
2
|
+
import { useDomain, useSubdomain } from "./composables/domain.mjs";
|
|
3
|
+
import { useDirectusAuth } from "./composables/auth.mjs";
|
|
4
|
+
import { addRouteMiddleware, defineNuxtPlugin, navigateTo, useRuntimeConfig } from "#app";
|
|
5
|
+
export default defineNuxtPlugin(async (nuxt) => {
|
|
6
|
+
const domain = useDomain();
|
|
7
|
+
const subdomain = useSubdomain();
|
|
8
|
+
if (nuxt.ssrContext) {
|
|
9
|
+
const { host } = nuxt.ssrContext.event.node.req.headers;
|
|
10
|
+
if (host) {
|
|
11
|
+
const { labels, domain: mainDomain, topLevelDomains } = parseDomain(
|
|
12
|
+
fromUrl(host)
|
|
13
|
+
);
|
|
14
|
+
if (mainDomain)
|
|
15
|
+
domain.value = `${mainDomain}.${topLevelDomains.join(".")}`;
|
|
16
|
+
else if (host.includes("localhost"))
|
|
17
|
+
domain.value = host.split(".").at(-1) ?? "";
|
|
18
|
+
else
|
|
19
|
+
domain.value = host;
|
|
20
|
+
subdomain.value = labels[0];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const config = useRuntimeConfig();
|
|
24
|
+
if (config.public.rolley.fetchUser)
|
|
25
|
+
await useDirectusAuth().fetchUser();
|
|
26
|
+
addRouteMiddleware("auth", async (to) => {
|
|
27
|
+
const user = useDirectusAuth().user;
|
|
28
|
+
if (!user.value) {
|
|
29
|
+
return navigateTo({
|
|
30
|
+
path: "/login",
|
|
31
|
+
query: { redirect: to.path !== "/" ? encodeURIComponent(to.path) : void 0 }
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
export declare function useDirectusAccessToken(event: H3Event): string | undefined;
|
|
3
|
+
export declare function useDirectusUrl(): string;
|
|
4
|
+
export declare function useDirectus(token?: string): import("@directus/sdk/dist/client-e8d6bf91").D<DirectusCollections> & import("@directus/sdk/dist/login-0506af09").d<DirectusCollections> & import("@directus/sdk/dist/login-0506af09").f<DirectusCollections>;
|
|
5
|
+
export declare function useAdminDirectus(): import("@directus/sdk/dist/client-e8d6bf91").D<DirectusCollections> & import("@directus/sdk/dist/login-0506af09").d<DirectusCollections> & import("@directus/sdk/dist/login-0506af09").f<DirectusCollections>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { authentication, createDirectus, rest } from "@directus/sdk";
|
|
2
|
+
import { getCookie } from "h3";
|
|
3
|
+
import { useRuntimeConfig } from "#imports";
|
|
4
|
+
export function useDirectusAccessToken(event) {
|
|
5
|
+
return getCookie(event, "directus_access_token");
|
|
6
|
+
}
|
|
7
|
+
export function useDirectusUrl() {
|
|
8
|
+
return useRuntimeConfig().public.rolley.url;
|
|
9
|
+
}
|
|
10
|
+
export function useDirectus(token) {
|
|
11
|
+
const url = useDirectusUrl();
|
|
12
|
+
if (!url)
|
|
13
|
+
throw new Error("DIRECTUS_URL is not set in config options or .env file");
|
|
14
|
+
const directus = createDirectus(url).with(authentication("json", { autoRefresh: false })).with(rest());
|
|
15
|
+
if (token)
|
|
16
|
+
directus.setToken(token);
|
|
17
|
+
return directus;
|
|
18
|
+
}
|
|
19
|
+
export function useAdminDirectus() {
|
|
20
|
+
const url = useDirectusUrl();
|
|
21
|
+
if (!url)
|
|
22
|
+
throw new Error("DIRECTUS_URL is not set in config options or .env file");
|
|
23
|
+
if (!process.env.DIRECTUS_ADMIN_TOKEN)
|
|
24
|
+
throw new Error("DIRECTUS_ADMIN_TOKEN is not set in config options or .env file");
|
|
25
|
+
const directus = createDirectus(url).with(authentication("json", { autoRefresh: false })).with(rest());
|
|
26
|
+
directus.setToken(process.env.DIRECTUS_ADMIN_TOKEN);
|
|
27
|
+
return directus;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDirectusUrl, useDirectus, useAdminDirectus, useDirectusAccessToken } from './directus';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDirectusUrl, useDirectus, useAdminDirectus, useDirectusAccessToken } from "./directus.mjs";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type DirectusThumbnailFormat = 'jpg' | 'png' | 'webp' | 'tiff'
|
|
2
|
+
export type DirectusThumbnailFit = 'cover' | 'contain' | 'inside' | 'outside'
|
|
3
|
+
|
|
4
|
+
export interface DirectusThumbnailOptions {
|
|
5
|
+
width?: number
|
|
6
|
+
height?: number
|
|
7
|
+
quality?: number
|
|
8
|
+
fit?: DirectusThumbnailFit
|
|
9
|
+
format?: DirectusThumbnailFormat
|
|
10
|
+
withoutEnlargement?: boolean
|
|
11
|
+
token?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface DirectusNotificationObject {
|
|
15
|
+
id?: number
|
|
16
|
+
timestamp?: string
|
|
17
|
+
status?: 'inbox' | 'archived'
|
|
18
|
+
recipient: Array<string> | string
|
|
19
|
+
sender?: Array<string> | string
|
|
20
|
+
subject: string
|
|
21
|
+
message?: string
|
|
22
|
+
collection?: string
|
|
23
|
+
item?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface DirectusQueryParams {
|
|
27
|
+
fields?: Array<string>
|
|
28
|
+
sort?: string | Array<string>
|
|
29
|
+
filter?: Record<string, unknown>
|
|
30
|
+
limit?: number
|
|
31
|
+
offset?: number
|
|
32
|
+
page?: number
|
|
33
|
+
alias?: string | Array<string>
|
|
34
|
+
deep?: Record<string, unknown>
|
|
35
|
+
search?: string
|
|
36
|
+
meta?: 'total_count' | 'filter_count' | '*'
|
|
37
|
+
}
|
|
38
|
+
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import { ModuleOptions } from './module'
|
|
3
|
+
|
|
4
|
+
declare module '@nuxt/schema' {
|
|
5
|
+
interface NuxtConfig { ['rolley']?: Partial<ModuleOptions> }
|
|
6
|
+
interface NuxtOptions { ['rolley']?: ModuleOptions }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare module 'nuxt/schema' {
|
|
10
|
+
interface NuxtConfig { ['rolley']?: Partial<ModuleOptions> }
|
|
11
|
+
interface NuxtOptions { ['rolley']?: ModuleOptions }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export { ModuleOptions, default } from './module'
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
import { ModuleOptions } from './module'
|
|
3
|
+
|
|
4
|
+
declare module '@nuxt/schema' {
|
|
5
|
+
interface NuxtConfig { ['rolley']?: Partial<ModuleOptions> }
|
|
6
|
+
interface NuxtOptions { ['rolley']?: ModuleOptions }
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
declare module 'nuxt/schema' {
|
|
10
|
+
interface NuxtConfig { ['rolley']?: Partial<ModuleOptions> }
|
|
11
|
+
interface NuxtOptions { ['rolley']?: ModuleOptions }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export { ModuleOptions, default } from './module'
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nuxt-directus-sdk",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.0.2",
|
|
5
|
+
"description": "A nuxt module that uses the directus SDK",
|
|
6
|
+
"author": "Matthew Rollinson <matt@rolley.io>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types.d.ts",
|
|
11
|
+
"import": "./dist/module.mjs",
|
|
12
|
+
"require": "./dist/module.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/module.cjs",
|
|
16
|
+
"types": "./dist/types.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"prepack": "nuxt-module-build",
|
|
22
|
+
"dev": "nuxi dev playground",
|
|
23
|
+
"dev:build": "nuxi build playground",
|
|
24
|
+
"dev:prepare": "nuxt-module-build --stub && nuxi prepare playground",
|
|
25
|
+
"release": "npm run lint && npm run prepack && changelogen --release && npm publish && git push --follow-tags",
|
|
26
|
+
"lint": "eslint .",
|
|
27
|
+
"test": "vitest run",
|
|
28
|
+
"test:watch": "vitest watch"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@directus/sdk": "^11.0.3",
|
|
32
|
+
"@nuxt/kit": "^3.7.1",
|
|
33
|
+
"change-case": "^4.1.2",
|
|
34
|
+
"defu": "^6.1.1",
|
|
35
|
+
"parse-domain": "^7.0.1",
|
|
36
|
+
"tippy.js": "^6.3.7",
|
|
37
|
+
"ufo": "^1.1.1",
|
|
38
|
+
"vue-toastification": "2.0.0-rc.5"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@nuxt/devtools": "latest",
|
|
42
|
+
"@nuxt/eslint-config": "^0.2.0",
|
|
43
|
+
"@nuxt/module-builder": "^0.5.1",
|
|
44
|
+
"@nuxt/schema": "^3.7.1",
|
|
45
|
+
"@nuxt/test-utils": "^3.7.1",
|
|
46
|
+
"@types/node": "^18.17.14",
|
|
47
|
+
"changelogen": "^0.5.5",
|
|
48
|
+
"nuxt": "^3.7.1",
|
|
49
|
+
"vitest": "^0.34.2"
|
|
50
|
+
},
|
|
51
|
+
"unbuild": {
|
|
52
|
+
"failOnWarn": false
|
|
53
|
+
}
|
|
54
|
+
}
|