├── .env-sample ├── .gitignore ├── README.md ├── data.db ├── data_agencyos.db ├── extensions └── directus-extension-my-bundle │ ├── dist │ ├── api.js │ └── app.js │ └── package.json ├── index.cjs ├── package.json ├── php-bo ├── cron │ └── my-job.php ├── inc.php ├── index.php └── lib │ ├── helper.php │ └── rb-mysql.php ├── script-quickstart.sh └── src-extensions └── my-bundle ├── .gitignore ├── package.json └── src ├── my-api └── index.js └── my-hooks └── index.js /.env-sample: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # 3 | # These values set environment variables which modify core settings of Directus. 4 | # 5 | # Values in square brackets are the default values. 6 | # 7 | # The following options are not all possible options. For more, see 8 | # https://docs.directus.io/self-hosted/config-options/ 9 | # 10 | #################################################################################################### 11 | #################################################################################################### 12 | 13 | ### General 14 | 15 | # IP or host the API listens on ["0.0.0.0"] 16 | HOST="0.0.0.0" 17 | 18 | # The port Directus will run on [8055] 19 | PORT=8055 20 | 21 | # The URL where your API can be reached on the web. It is also used for things like OAuth redirects, 22 | # forgot-password emails, and logos that needs to be publicly available on the internet. ["/"] 23 | PUBLIC_URL="/" 24 | # PUBLIC_URL="http://localhost:8055" 25 | 26 | # What level of detail to log. [info] 27 | # "fatal", "error", "warn", "info", "debug", "trace", "silent" 28 | # LOG_LEVEL="info" 29 | 30 | # Render the logs human readable (pretty) or as JSON (raw), [pretty] 31 | # "pretty", "raw" 32 | # LOG_STYLE="pretty" 33 | 34 | # Controls the maximum request body size. Accepts number of bytes, or human readable string ["1mb"] 35 | # MAX_PAYLOAD_SIZE="1mb" 36 | 37 | # Where to redirect to when navigating to /. Accepts a relative path, absolute URL, or false to disable ["./admin"] 38 | # ROOT_REDIRECT="./admin" 39 | 40 | # Whether or not to serve the Admin App under /admin. [true] 41 | # SERVE_APP=true 42 | 43 | # Whether or not to enable GraphQL Introspection [true] 44 | # GRAPHQL_INTROSPECTION=true 45 | 46 | # Limit the maximum amount of items that can get requested in one query. 47 | # QUERY_LIMIT_DEFAULT=100 48 | # QUERY_LIMIT_MAX=Infinity 49 | 50 | # The maximum number of items for batch mutations when creating, updating and deleting. ["Infinity"] 51 | # MAX_BATCH_MUTATION="Infinity" 52 | 53 | # Shared Redis server for things like caching, rate limiting, container synchronization, etc 54 | # REDIS="redis://@127.0.0.1:6379" 55 | 56 | #################################################################################################### 57 | ### Database 58 | 59 | # All DB_* environment variables are passed to the connection configuration of a Knex instance. 60 | # Based on your project's needs, you can extend the DB_* environment variables with any config 61 | # you need to pass to the database instance. 62 | 63 | DB_CLIENT="sqlite3" 64 | DB_FILENAME="/home/kulkarni005/Work/Yohita/repos/directus-project-with-extensions-quickstart/data.db" 65 | 66 | 67 | 68 | # These match the databases defined in the docker-compose file in the root of this repo 69 | 70 | ## Postgres 71 | # DB_CLIENT="pg" 72 | # DB_HOST="localhost" 73 | # DB_PORT=5432 74 | # DB_DATABASE="directus" 75 | # DB_USER="postgres" 76 | # DB_PASSWORD="secret" 77 | 78 | ## CockroachDB 79 | # DB_CLIENT="cockroachdb" 80 | # DB_HOST="localhost" 81 | # DB_PORT=26257 82 | # DB_DATABASE="directus" 83 | # DB_USER="root" 84 | # DB_PASSWORD="" 85 | 86 | ## MySQL 8 87 | # DB_CLIENT="mysql" 88 | # DB_HOST="localhost" 89 | # DB_PORT=3306 90 | # DB_DATABASE="directus" 91 | # DB_USER="root" 92 | # DB_PASSWORD="secret" 93 | 94 | ## MariaDB 95 | # DB_CLIENT="mysql" 96 | # DB_HOST="localhost" 97 | # DB_PORT=3306 98 | # DB_DATABASE="directus" 99 | # DB_USER="root" 100 | # DB_PASSWORD="secret" 101 | 102 | ## MS SQL 103 | # DB_CLIENT="mssql" 104 | # DB_HOST="localhost" 105 | # DB_PORT=1343 106 | # DB_DATABASE="directus" 107 | # DB_USER="sa" 108 | # DB_PASSWORD="Test@123" 109 | 110 | ## OracleDB 111 | # DB_CLIENT="oracledb" 112 | # DB_CONNECT_STRING="localhost:1521/XE" 113 | # DB_USER="secretsysuser" 114 | # DB_PASSWORD="secretpassword" 115 | 116 | ## SQLite Example 117 | # DB_CLIENT="sqlite3" 118 | # DB_FILENAME="./data.db" 119 | 120 | ## MySQL 5.7 121 | # DB_CLIENT="mysql" 122 | # DB_HOST="localhost" 123 | # DB_PORT=3306 124 | # DB_DATABASE="directus" 125 | # DB_USER="root" 126 | # DB_PASSWORD="secret" 127 | 128 | #################################################################################################### 129 | ### Rate Limiting 130 | 131 | # Whether or not to enable rate limiting on the API [false] 132 | RATE_LIMITER_ENABLED=false 133 | 134 | # Where to store the rate limiter counts [memory] 135 | # memory, redis 136 | RATE_LIMITER_STORE=memory 137 | 138 | # The amount of allowed hits per duration [50] 139 | RATE_LIMITER_POINTS=25 140 | 141 | # The time window in seconds in which the hits are counted [1] 142 | RATE_LIMITER_DURATION=1 143 | 144 | #################################################################################################### 145 | ### Caching 146 | 147 | # Whether or not caching is enabled. [false] 148 | CACHE_ENABLED=false 149 | 150 | # How long the cache is persisted ["5m"] 151 | # CACHE_TTL="30m" 152 | 153 | # How to scope the cache data ["system-cache"] 154 | # CACHE_NAMESPACE="system-cache" 155 | 156 | # Automatically purge the cache on create, update, and delete actions. [false] 157 | # CACHE_AUTO_PURGE=true 158 | 159 | # List of collections that prevent cache purging when `CACHE_AUTO_PURGE` is enabled. ["directus_activity,directus_presets"] 160 | # CACHE_AUTO_PURGE_IGNORE_LIST="directus_activity,directus_presets" 161 | 162 | # memory | redis 163 | CACHE_STORE=memory 164 | 165 | # How long assets will be cached for in the browser. Sets the max-age value of the Cache-Control header ["30d"] 166 | ASSETS_CACHE_TTL="30d" 167 | 168 | #################################################################################################### 169 | ### File Storage 170 | 171 | # A CSV of storage locations (eg: local,digitalocean,amazon) to use. You can use any names you'd like for these keys ["local"] 172 | STORAGE_LOCATIONS="local" 173 | STORAGE_LOCAL_DRIVER="local" 174 | STORAGE_LOCAL_ROOT="./uploads" 175 | 176 | ## S3 Example (location name: DigitalOcean) 177 | # STORAGE_DIGITALOCEAN_DRIVER="s3" 178 | # STORAGE_DIGITALOCEAN_KEY="abcdef" 179 | # STORAGE_DIGITALOCEAN_SECRET="ghijkl" 180 | # STORAGE_DIGITALOCEAN_ENDPOINT="https://ams3.digitaloceanspaces.com" 181 | # STORAGE_DIGITALOCEAN_BUCKET="my-files" 182 | # STORAGE_DIGITALOCEAN_REGION="ams3" 183 | 184 | ## Google Cloud Storage Example (location name: Google) 185 | # STORAGE_GOOGLE_DRIVER="gcs" 186 | # STORAGE_GOOGLE_KEY_FILENAME="abcdef" 187 | # STORAGE_GOOGLE_BUCKET="my-files" 188 | 189 | 190 | ## A comma-separated list of metadata keys to collect during file upload. Use * for all 191 | # Extracting all metadata might cause memory issues when the file has an unusually large set of metadata 192 | # [ifd0.Make,ifd0.Model,exif.FNumber,exif.ExposureTime,exif.FocalLength,exif.ISO] 193 | # FILE_METADATA_ALLOW_LIST= 194 | 195 | #################################################################################################### 196 | ### Security 197 | 198 | KEY="39aa2e76-8ec1-4f35-9d35-6435f8a3b452" 199 | SECRET="Q6d4yYSXnU0IElq4_AnRpI7SBw9FHDYe" 200 | 201 | 202 | # Unique identifier for the project 203 | # KEY="xxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" 204 | 205 | # Secret string for the project 206 | # SECRET="abcdef" 207 | 208 | # The duration that the access token is valid ["15m"] 209 | ACCESS_TOKEN_TTL="15m" 210 | 211 | # The duration that the refresh token is valid, and also how long users stay logged-in to the App ["7d"] 212 | REFRESH_TOKEN_TTL="7d" 213 | 214 | # Whether or not to use a secure cookie for the refresh token in cookie mode [false] 215 | REFRESH_TOKEN_COOKIE_SECURE=false 216 | 217 | # Value for sameSite in the refresh token cookie when in cookie mode ["lax"] 218 | REFRESH_TOKEN_COOKIE_SAME_SITE="lax" 219 | 220 | # Name of refresh token cookie ["directus_refresh_token"] 221 | REFRESH_TOKEN_COOKIE_NAME="directus_refresh_token" 222 | 223 | # Which domain to use for the refresh cookie. Useful for development mode. 224 | # REFRESH_TOKEN_COOKIE_DOMAIN 225 | 226 | # The duration in milliseconds that a login request will be stalled for, 227 | # and it should be greater than the time taken for a login request with an invalid password [500] 228 | # LOGIN_STALL_TIME=500 229 | 230 | # Whether or not to enable the CORS headers [false] 231 | CORS_ENABLED=true 232 | 233 | # Value for the Access-Control-Allow-Origin header. Use true to match the Origin header, or provide a domain or a CSV of domains for specific access [false] 234 | CORS_ORIGIN=true 235 | 236 | # Value for the Access-Control-Allow-Methods header [GET,POST,PATCH,DELETE] 237 | CORS_METHODS=GET,POST,PATCH,DELETE 238 | 239 | # Value for the Access-Control-Allow-Headers header [Content-Type,Authorization] 240 | CORS_ALLOWED_HEADERS=Content-Type,Authorization 241 | 242 | # Value for the Access-Control-Expose-Headers header [Content-Range] 243 | CORS_EXPOSED_HEADERS=Content-Range 244 | 245 | # Whether or not to send the Access-Control-Allow-Credentials header [true] 246 | CORS_CREDENTIALS=true 247 | 248 | # Value for the Access-Control-Max-Age header [18000] 249 | CORS_MAX_AGE=18000 250 | 251 | #################################################################################################### 252 | ### Argon2 253 | 254 | # How much memory to use when generating hashes, in KiB [4096] 255 | # HASH_MEMORY_COST=81920 256 | 257 | # The length of the hash function output in bytes [32] 258 | # HASH_HASH_LENGTH=32 259 | 260 | # The amount of passes (iterations) used by the hash function. It increases hash strength at the cost of time required to compute [3] 261 | # HASH_TIME_COST=10 262 | 263 | # The amount of threads to compute the hash on. Each thread has a memory pool with HASH_MEMORY_COST size [1] 264 | # HASH_PARALLELISM=2 265 | 266 | # The variant of the hash function (0: argon2d, 1: argon2i, or 2: argon2id) [2] 267 | # HASH_TYPE=2 268 | 269 | # An extra and optional non-secret value. The value will be included B64 encoded in the parameters portion of the digest [] 270 | # HASH_ASSOCIATED_DATA=foo 271 | 272 | #################################################################################################### 273 | ### Auth Providers 274 | 275 | # A comma-separated list of auth providers [] 276 | AUTH_PROVIDERS="" 277 | # AUTH_PROVIDERS="github" 278 | 279 | # AUTH_GITHUB_DRIVER="oauth2" 280 | # AUTH_GITHUB_CLIENT_ID="73e...4b" 281 | # AUTH_GITHUB_CLIENT_SECRET="b9...98" 282 | # AUTH_GITHUB_AUTHORIZE_URL="https://github.com/login/oauth/authorize" 283 | # AUTH_GITHUB_ACCESS_URL="https://github.com/login/oauth/access_token" 284 | # AUTH_GITHUB_PROFILE_URL="https://api.github.com/user" 285 | # AUTH_GITHUB_ALLOW_PUBLIC_REGISTRATION=true 286 | # AUTH_GITHUB_DEFAULT_ROLE_ID="82424427-c9d4-4289-8bc5-ed1bf8422c90" 287 | # AUTH_GITHUB_ICON="github" 288 | # AUTH_GITHUB_LABEL="GitHub" 289 | # AUTH_GITHUB_EMAIL_KEY="email" 290 | # AUTH_GITHUB_IDENTIFIER_KEY="login" 291 | 292 | #################################################################################################### 293 | ### Extensions 294 | 295 | # Path to your local extensions folder ["./extensions"] 296 | EXTENSIONS_PATH="./extensions" 297 | 298 | # Automatically reload extensions when they have changed [false] 299 | EXTENSIONS_AUTO_RELOAD=false 300 | 301 | #################################################################################################### 302 | ### Email 303 | 304 | # Email address from which emails are sent ["no-reply@directus.io"] 305 | EMAIL_FROM="no-reply@directus.io" 306 | 307 | # What to use to send emails. One of 308 | # sendmail, smtp, mailgun, sendgrid, ses. 309 | EMAIL_TRANSPORT="sendmail" 310 | EMAIL_SENDMAIL_NEW_LINE="unix" 311 | EMAIL_SENDMAIL_PATH="/usr/sbin/sendmail" 312 | 313 | ## Email (Sendmail Transport) 314 | 315 | # What new line style to use in sendmail ["unix"] 316 | # EMAIL_SENDMAIL_NEW_LINE="unix" 317 | 318 | # Path to your sendmail executable ["/usr/sbin/sendmail"] 319 | # EMAIL_SENDMAIL_PATH="/usr/sbin/sendmail" 320 | 321 | ## Email (SMTP Transport) 322 | # EMAIL_SMTP_HOST="localhost" 323 | 324 | # Use SMTP pooling 325 | # EMAIL_SMTP_POOL=true 326 | # EMAIL_SMTP_PORT=465 327 | # EMAIL_SMTP_SECURE=false # Use TLS 328 | # EMAIL_SMTP_IGNORE_TLS=false 329 | # EMAIL_SMTP_USER="username" 330 | # EMAIL_SMTP_PASSWORD="password" 331 | 332 | ## Email (Mailgun Transport) 333 | # EMAIL_MAILGUN_API_KEY="key-1234123412341234" 334 | # EMAIL_MAILGUN_DOMAIN="a domain name from https://app.mailgun.com/app/sending/domains" 335 | 336 | ## Email (SendGrid Transport) 337 | # EMAIL_SENDGRID_API_KEY="key-1234123412341234" 338 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *~ 3 | *.sw[mnpcod] 4 | .tmp 5 | *.tmp 6 | *.tmp.* 7 | *.sublime-project 8 | *.sublime-workspace 9 | .DS_Store 10 | Thumbs.db 11 | UserInterfaceState.xcuserstate 12 | $RECYCLE.BIN/ 13 | 14 | *.log 15 | log.txt 16 | npm-debug.log* 17 | 18 | /.idea 19 | /.ionic 20 | /.sass-cache 21 | /.sourcemaps 22 | /.versions 23 | /.vscode 24 | /coverage 25 | /node_modules 26 | node_modules 27 | /platforms 28 | /plugins 29 | /www 30 | package-lock.json 31 | .env 32 | public/cache 33 | public/uploads 34 | /uploads 35 | /bo/gen_files/* 36 | /bo/vendor 37 | composer.lock 38 | vendor 39 | 40 | # Ignore dist folder in all directories 41 | /dist/ 42 | 43 | # Allow dist folder in extensions and its subdirectories 44 | !/extensions/**/dist/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Directus Project with Extensions Quickstart 2 | 3 | ![Directus Logo](https://directus.io/_nuxt/logo-dark.8a22a14a.svg) 4 | 5 | ## Table of Contents 6 | 7 | - [About Directus](#about-directus) 8 | - [Getting Started](#getting-started) 9 | - [Extension Development](#extension-development) 10 | - [Usage](#usage) 11 | 12 | ## About Directus 13 | 14 | [Directus](https://directus.io/) is an open-source headless CMS that provides a powerful and flexible interface for managing your content and databases. It allows you to create, customize, and manage your content models and data with ease, making it a great choice for building content-driven applications - supercharged with APIs. 15 | 16 | Download Directus Quickstart handbook : https://yohita.com/web/downloads/Directus%20Quickstart%20Handbook%20-%200.1.pdf 17 | 18 | **Check Below Video from YouTube :** 19 | 20 | [![Youtube Video](https://img.youtube.com/vi/q6WGvEZvPrE/0.jpg)](https://www.youtube.com/watch?v=q6WGvEZvPrE) 21 | 22 | ## Getting Started 23 | 24 | To quickly set up a Directus project with extension development capabilities, follow these steps: 25 | 26 | 1. **Clone the Repository**: Clone this repository to your local machine using the following command: 27 | 28 | git clone https://github.com/Yohita/directus-project-with-extensions-quickstart.git 29 | 30 | 2. **Install Dependencies**: Navigate to the project directory and install the necessary dependencies using: 31 | 32 | - cd directus-project-with-extensions-quickstart 33 | - npm install 34 | 35 | 3. Change patth to data.db in .env file to your file path 36 | 37 | 4. **Start the Development Server**: Start the development server to begin working with Directus: 38 | - bash script-quickstart.sh 39 | 40 | - OR 41 | 42 | - node index.cjs 43 | 44 | ## 🚀 Hot Reloading for Directus Extension Development 45 | 46 | To enable **hot reloading** while developing Directus extensions, follow these steps: 47 | 48 | ### **1. Install `nodemon`** (if not already installed) 49 | npm install -g nodemon 50 | 51 | ### **1. Start Development Mode 52 | npm run dev 53 | 54 | **Thats it !** 55 | - Server is running on http://localhost:8055 56 | - my-api on : http://localhost:8055/my-api 57 | - api raw database access : http://localhost:8055/my-api/product-list-raw-dbaccess-test 58 | - api data access using directus item service : http://localhost:8055/my-api/product-list-item-service-api-test 59 | 60 | ## Applying a Template to Blank Instance 61 | 2. Login and create a Static Access Token for the admin user. 62 | 3. Copy the static token and your Directus URL. (http://localhost:8055) 63 | 4. Run the following command on the terminal and follow the prompts. 64 | 65 | ``` 66 | $ npx directus-template-cli@latest apply 67 | ``` 68 | 69 | **Development Mode build and run** : script-quickstart.sh to prepare project and run , do this when we do any changes in extension souce 70 | bash script-quickstart.sh 71 | 72 | **Notes** 73 | 1. Admin Credentails 74 | Email : admin@admin.com 75 | Password : admin123 76 | 2. This project uses SQLite for quickstart, but you can connect to any other database simply by configuring the .env file. 77 | 78 | ## Using Mysql Instead of SQLITe : 79 | Run command : 'npx directus init' 80 | This will create .env with your mysql credentials 81 | 82 | ## Using PHP php-bo (PHP BackOffice) 83 | I work on both NodeJS scripts as well as PHP in my project , 84 | I have added little helper to help you with that in php folder 85 | It Parses and use .env file of root directory 86 | Only Supports MySql as of now. 87 | 88 | ## Usage 89 | 90 | You can use this Directus project as a foundation for building various content-driven applications. Customize your content models, create data relationships, and extend Directus to suit your specific project requirements. 91 | 92 | 93 | For detailed information on how to use Directus, refer to the official [Directus Documentation](https://docs.directus.io/). 94 | 95 | ## Extension Development 96 | 97 | This project includes the tools and structure for developing extensions for Directus. You can find extension development resources and examples in the src-extensions directory. To get started with extension development, follow these steps: 98 | 99 | **Check Below Video from YouTube :** 100 | 101 | [![Youtube Video](https://img.youtube.com/vi/dY96SwsR_3Y/0.jpg)](https://www.youtube.com/watch?v=dY96SwsR_3Y) 102 | 103 | 1. **Create an Extension**: Inside the `src-extensions/my-bundle` directory. 104 | 1. Install "npm i" 105 | 2. Start with "npm run add" 106 | Follow Official Documentation Here [Directus Bundle Extension](https://docs.directus.io/extensions/bundles.html) 107 | 108 | 4. **Develop Your Extension**: Add your custom code and logic to your extension directory. You can use the provided examples as a reference. 109 | 110 | 5. **Test Your Extension**: 111 | Run "bash script-quickstart.sh" to build , move and start project with your extension 112 | 113 | 114 | ## Deployment 115 | Treat this project as just another Node.js project and follow standard deployment procedures. No special actions are needed. 116 | Simply update your database configuration accordingly in the .env file. 117 | 118 | VPS with a minimum of 2 GB of RAM should be sufficient to run both MySQL and the Node.js project for moderately heavy traffic. 119 | 120 | **Check Below Video from YouTube :** 121 | 122 | [![Youtube Video](https://img.youtube.com/vi/HqSYPM6gX0o/0.jpg)](https://www.youtube.com/watch?v=HqSYPM6gX0o) 123 | -------------------------------------------------------------------------------- /data.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yohita/directus-project-with-extensions-quickstart/ea55f7c0cf2a4eeebb93697b3aa2f2f2eee01cc0/data.db -------------------------------------------------------------------------------- /data_agencyos.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yohita/directus-project-with-extensions-quickstart/ea55f7c0cf2a4eeebb93697b3aa2f2f2eee01cc0/data_agencyos.db -------------------------------------------------------------------------------- /extensions/directus-extension-my-bundle/dist/api.js: -------------------------------------------------------------------------------- 1 | const e=[{name:"my-hooks",config:({filter:e,action:t})=>{e("items.create",(()=>{console.log("Creating Item!")})),t("items.create",(()=>{console.log("Item created!")}))}}],t=[{name:"my-api",config:(e,{services:t,database:a})=>{const{ItemsService:s}=t;e.get("/",((e,t)=>t.send("Hello, World!"))),e.get("/product-list-raw-dbaccess-test",(async(e,t)=>{let s=await a("products");t.send({data:s})})),e.get("/product-list-item-service-api-test",(async(e,t)=>{let a=new s("products",{schema:e.schema,accountability:e.accountability}),c=await a.readByQuery({fields:["id","name"],filter:{}});t.send({data:c})}))}}],a=[];export{t as endpoints,e as hooks,a as operations}; 2 | -------------------------------------------------------------------------------- /extensions/directus-extension-my-bundle/dist/app.js: -------------------------------------------------------------------------------- 1 | const o=[],t=[],c=[],e=[],n=[],p=[],r=[];export{t as displays,o as interfaces,c as layouts,e as modules,r as operations,n as panels,p as themes}; 2 | -------------------------------------------------------------------------------- /extensions/directus-extension-my-bundle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "directus-extension-my-bundle", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "directus:extension": { 6 | "host": "^10.1.10", 7 | "type": "bundle", 8 | "path": { 9 | "app": "dist/app.js", 10 | "api": "dist/api.js" 11 | }, 12 | "entries": [ 13 | { 14 | "type": "endpoint", 15 | "name": "my-api", 16 | "source": "src/my-api/index.js" 17 | }, 18 | { 19 | "type": "hook", 20 | "name": "my-hooks", 21 | "source": "src/my-hooks/index.js" 22 | } 23 | 24 | ] 25 | }, 26 | "description": "Please enter a description for your extension", 27 | "icon": "extension", 28 | "keywords": [ 29 | "directus", 30 | "directus-extension", 31 | "directus-custom-bundle" 32 | ], 33 | "scripts": { 34 | "build": "directus-extension build", 35 | "dev": "directus-extension build -w --no-minify", 36 | "link": "directus-extension link", 37 | "add": "directus-extension add" 38 | }, 39 | "devDependencies": { 40 | "@directus/extensions-sdk": "12.1.4", 41 | "vue": "^3.5.13" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /index.cjs: -------------------------------------------------------------------------------- 1 | async function main() { 2 | const { startServer } = await import('@directus/api/server'); 3 | startServer(); 4 | } 5 | 6 | main(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "directus-project-with-extensions-quickstart", 3 | "description": "Directus project with extensions quickstart", 4 | "author": { 5 | "name": "Amit Kulkarni", 6 | "url": "https://yohita.com" 7 | }, 8 | "version": "11.6.1", 9 | "scripts": { 10 | "dev": "nodemon --watch src-extensions/my-bundle/src --ext js,ts,json,vue --exec \"bash script-quickstart.sh\"" 11 | }, 12 | "dependencies": { 13 | "directus": "11.6.1", 14 | "sqlite3": "^5.1.7" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /php-bo/cron/my-job.php: -------------------------------------------------------------------------------- 1 | 5, // in seconds 13 | PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 14 | 15 | //Fix for Tables containing underscores and caps 16 | R::ext('xdispense', function($type){ 17 | return R::getRedBean()->dispense( $type); 18 | }); 19 | 20 | //Freezing DB Schema 21 | R::freeze( TRUE ); 22 | R::useWriterCache(true); 23 | if($_REQUEST['debug'] ?? '' == 6969){ 24 | $GLOBALS['IS_DEBUG']=true; 25 | R::debug(true); 26 | R::fancyDebug(true); 27 | $IS_CACHE=false; 28 | } else{ 29 | $GLOBALS['IS_DEBUG']=false; 30 | R::debug(false); 31 | R::fancyDebug(false); 32 | } -------------------------------------------------------------------------------- /php-bo/index.php: -------------------------------------------------------------------------------- 1 | = 32 && $ord <= 126) 81 | $return .= $char; 82 | else 83 | $return .= '\\x' . dechex($ord); 84 | } 85 | return $return; 86 | } 87 | ?> -------------------------------------------------------------------------------- /script-quickstart.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the directory where this script is located 4 | script_directory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 5 | 6 | #run npm i if node_modules does not exist 7 | if [ ! -d "$script_directory/node_modules" ]; then 8 | npm i 9 | fi 10 | 11 | # Parent directory where your subdirectories are located 12 | parent_directory="$script_directory/src-extensions" 13 | 14 | # Directory where you want to copy the 'dist' folders 15 | destination_directory="$script_directory/extensions" 16 | 17 | # Loop through each subdirectory in the parent directory 18 | for directory in $parent_directory/*; do 19 | 20 | # Go to Directory 21 | cd $directory 22 | echo $directory; 23 | 24 | #check if node_modules exists, if not run npm i 25 | if [ ! -d "$directory/node_modules" ]; then 26 | npm i 27 | fi 28 | 29 | # Build the extension 30 | npm run build 31 | 32 | # Get the name of the subdirectory 33 | directory_name=${directory##*/} 34 | 35 | # Target Directory name with directus-extension prefix 36 | directory_name="directus-extension-$directory_name" 37 | 38 | # Create the destination directory if it doesn't exist 39 | mkdir -p $destination_directory/$directory_name 40 | 41 | # Copy the 'dist' folder to the destination directory 42 | cp -r $directory/dist $destination_directory/$directory_name 43 | # copy package-json 44 | cp $directory/package.json $destination_directory/$directory_name 45 | done 46 | 47 | #check if uploads folder exists if not create it 48 | if [ ! -d "$script_directory/uploads" ]; then 49 | mkdir -p $script_directory/uploads 50 | fi 51 | 52 | 53 | #check if .env file exists if not copy .env-sample to .env 54 | if [ ! -f "$script_directory/.env" ]; then 55 | cp $script_directory/.env-sample $script_directory/.env 56 | 57 | # Define the new value for DB_FILENAME 58 | new_db_filename="$script_directory/data.db" 59 | 60 | # Escape the special characters in the new value 61 | escaped_db_filename=$(echo "$new_db_filename" | sed 's/[\/&]/\\&/g') 62 | 63 | # Use sed to update the DB_FILENAME variable in the .env file 64 | sed -i.bak "s|^\(DB_FILENAME=\)\".*\"$|\1\"$new_db_filename\"|" "$script_directory/.env" && rm "$script_directory/.env.bak" 65 | 66 | fi 67 | 68 | 69 | #cd to script_directory 70 | cd $script_directory 71 | 72 | # Run the index.cjs file to start the server 73 | node index.cjs 74 | 75 | 76 | -------------------------------------------------------------------------------- /src-extensions/my-bundle/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | dist 4 | -------------------------------------------------------------------------------- /src-extensions/my-bundle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "directus-extension-my-bundle", 3 | "version": "1.0.0", 4 | "type": "module", 5 | "directus:extension": { 6 | "host": "^10.1.10", 7 | "type": "bundle", 8 | "path": { 9 | "app": "dist/app.js", 10 | "api": "dist/api.js" 11 | }, 12 | "entries": [ 13 | { 14 | "type": "endpoint", 15 | "name": "my-api", 16 | "source": "src/my-api/index.js" 17 | }, 18 | { 19 | "type": "hook", 20 | "name": "my-hooks", 21 | "source": "src/my-hooks/index.js" 22 | } 23 | 24 | ] 25 | }, 26 | "description": "Please enter a description for your extension", 27 | "icon": "extension", 28 | "keywords": [ 29 | "directus", 30 | "directus-extension", 31 | "directus-custom-bundle" 32 | ], 33 | "scripts": { 34 | "build": "directus-extension build", 35 | "dev": "directus-extension build -w --no-minify", 36 | "link": "directus-extension link", 37 | "add": "directus-extension add" 38 | }, 39 | "devDependencies": { 40 | "@directus/extensions-sdk": "12.1.4", 41 | "vue": "^3.5.13" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src-extensions/my-bundle/src/my-api/index.js: -------------------------------------------------------------------------------- 1 | export default (router,{services,database}) => { 2 | const { ItemsService } = services; 3 | 4 | 5 | router.get('/', (req, res) => res.send('Hello, World!')); 6 | 7 | router.get('/product-list-raw-dbaccess-test', async (req, res) => { 8 | 9 | //access the table products in old db way - Directus uses KNEX https://knexjs.org/ 10 | let products = await database('products'); 11 | res.send({data:products}); 12 | }); 13 | 14 | router.get('/product-list-item-service-api-test', async (req, res) => { 15 | //access the products using ItemService 16 | //this will trigger all flows and hooks attached to this collection 17 | 18 | let productsService = new ItemsService('products',{schema:req.schema,accountability:req.accountability}); 19 | //filter documentation 20 | //fields is array of fields to return can be * for all 21 | //for foreign fields use supplier.* to get all fields from supplier of product 22 | 23 | let products = await productsService.readByQuery({fields:["id","name"],filter:{}}); 24 | res.send({data:products}); 25 | 26 | }); 27 | 28 | }; 29 | -------------------------------------------------------------------------------- /src-extensions/my-bundle/src/my-hooks/index.js: -------------------------------------------------------------------------------- 1 | export default ({ filter, action }) => { 2 | filter('items.create', () => { 3 | console.log('Creating Item!'); 4 | }); 5 | 6 | action('items.create', () => { 7 | console.log('Item created!'); 8 | }); 9 | }; 10 | --------------------------------------------------------------------------------