|
| 1 | +--- |
| 2 | +title: "Attack of the Decorators - A New Hope for Eclipse Dirigible Developers" |
| 3 | +description: "The Attack of the Decorators is here, and with it comes a wave of new TypeScript superpowers that dramatically simplify Dependency Injection, Entities, Jobs, Listeners, WebSockets, Controllers, Roles, and Extensions." |
| 4 | +author: Nedelcho Delchev |
| 5 | +author_gh_user: delchev |
| 6 | +author_avatar: https://avatars.githubusercontent.com/u/6852373?v=4 |
| 7 | +read_time: 5 min |
| 8 | +publish_date: December 04, 2025 |
| 9 | +--- |
| 10 | + |
| 11 | +In a galaxy not so far away - specifically, the Dirigible runtime - a silent revolution has begun. |
| 12 | +Where once developers roamed the dusty deserts of boilerplate code, a new army has emerged: Decorators. |
| 13 | + |
| 14 | +Elegant. Precise. Opinionated. |
| 15 | + |
| 16 | +<img src="../../../../images/decorators/decorators.jpg" alt="decorators.jpg"> |
| 17 | + |
| 18 | +Some call them syntactic sugar. |
| 19 | +Others call them magic. |
| 20 | +But in Dirigible… they are *the chosen ones*. |
| 21 | + |
| 22 | +The Attack of the Decorators is here, and with it comes a wave of new TypeScript superpowers that dramatically simplify Dependency Injection, Entities, Jobs, Listeners, WebSockets, Controllers, Roles, and Extensions. |
| 23 | + |
| 24 | +Let us witness the rise of this new army - and the fall of verbosity. |
| 25 | + |
| 26 | +## Episode I: The Phantom Dependency Injection |
| 27 | + |
| 28 | +For years, Jedi developers manually wired components together using pure JavaScript. But those days are over. |
| 29 | + |
| 30 | +The Dependency Injection Decorators have arrived: |
| 31 | + |
| 32 | +* `@Component` |
| 33 | +* `@Injected` |
| 34 | +* `@Inject` |
| 35 | + |
| 36 | +You can now summon your services as easily as calling the Force. |
| 37 | + |
| 38 | +Across the sand dunes of *PaymentComponent.ts*: |
| 39 | + |
| 40 | +```ts |
| 41 | +@Component('myPaymentService') |
| 42 | +export class PaymentComponent { |
| 43 | + public doPayment(paymentData: any): any { |
| 44 | + return { status: "OK", data: paymentData }; |
| 45 | + } |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +And in the hidden temple of *OrderProcessor.ts*: |
| 50 | + |
| 51 | +```ts |
| 52 | +@Injected() |
| 53 | +class OrderProcessor { |
| 54 | + |
| 55 | + @Inject('myPaymentService') |
| 56 | + paymentComponent!: PaymentComponent; |
| 57 | + |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | +No XML holocrons. No config files. The Force binds everything together. |
| 62 | + |
| 63 | +GitHub Sample: [dirigiblelabs/sample-component-decorators](https://github.com/dirigiblelabs/sample-component-decorators) |
| 64 | + |
| 65 | +## Episode II: Attack of the Cron Expressions |
| 66 | + |
| 67 | +They said jobs were difficult. |
| 68 | +They said scheduling was tedious. |
| 69 | +But they had not met the `@Scheduled` decorator. |
| 70 | + |
| 71 | +```ts |
| 72 | +@Scheduled({ expression: "0/10 * * * * ?" }) |
| 73 | +export class MyJob { |
| 74 | + run() { |
| 75 | + console.log("MyJob executed!"); |
| 76 | + } |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +Every 10 seconds, a new execution. Like clockwork. Like droids marching across Geonosis. |
| 81 | + |
| 82 | +GitHub Sample: [dirigiblelabs/sample-job-decorator](https://github.com/dirigiblelabs/sample-job-decorator) |
| 83 | + |
| 84 | +## Episode III: Revenge of the Listeners |
| 85 | + |
| 86 | +A disturbance in the queue you sense… |
| 87 | +A message is coming. |
| 88 | + |
| 89 | +And who will answer? |
| 90 | +A Listener will. |
| 91 | + |
| 92 | +```ts |
| 93 | +@Listener({ |
| 94 | + name: "sample-listener-decorator/OrderListener", |
| 95 | + kind: "queue" |
| 96 | +}) |
| 97 | +export class OrderListener { |
| 98 | + public static onMessage(message: string) { |
| 99 | + console.log("Processing message event:", message); |
| 100 | + } |
| 101 | +} |
| 102 | +``` |
| 103 | + |
| 104 | +A producer triggers it. |
| 105 | +The Listener awakens. |
| 106 | +Balance is restored. |
| 107 | + |
| 108 | +GitHub Sample: [dirigiblelabs/sample-listener-decorator](https://github.com/dirigiblelabs/sample-listener-decorator) |
| 109 | + |
| 110 | +## Episode IV: A New WebSocket |
| 111 | + |
| 112 | +The Clone Army now spans galaxies — including the real-time domain. |
| 113 | + |
| 114 | +WebSockets join the battle with the `@Websocket` decorator: |
| 115 | + |
| 116 | +```ts |
| 117 | +@Websocket({ |
| 118 | + name: "sample-websocket-decorator/OrderWebsocket", |
| 119 | + endpoint: "order-ws" |
| 120 | +}) |
| 121 | +export class OrderWebsocket { |
| 122 | + public static onMessage(message: string) { |
| 123 | + return `Hello from OrderWebsocket! [${message}]`; |
| 124 | + } |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +Connections open. |
| 129 | +Messages fly. |
| 130 | +The council approves. |
| 131 | + |
| 132 | +GitHub Sample: [dirigiblelabs/sample-websocket-decorator](https://github.com/dirigiblelabs/sample-websocket-decorator) |
| 133 | + |
| 134 | +## Episode V: The ORM Strikes Back |
| 135 | + |
| 136 | +The Entity decorators bring order to the database. An entire Jedi Archive — structured, typed, documented. |
| 137 | + |
| 138 | +Decorators include: |
| 139 | + |
| 140 | +* `@Entity` |
| 141 | +* `@Table` |
| 142 | +* `@Column` |
| 143 | +* `@Id` |
| 144 | +* `@Generated` |
| 145 | +* `@Documentation` |
| 146 | +* `@OneToMany`, `@ManyToOne` |
| 147 | + |
| 148 | +```ts |
| 149 | +@Entity("CountryEntity") |
| 150 | +@Table("SAMPLE_COUNTRY") |
| 151 | +export class CountryEntity { |
| 152 | + |
| 153 | + @Id() |
| 154 | + @Generated("sequence") |
| 155 | + @Column({ name: "COUNTRY_ID", type: "long" }) |
| 156 | + public Id?: number; |
| 157 | + |
| 158 | + @Column({ name: "COUNTRY_NAME", type: "string" }) |
| 159 | + public Name?: string; |
| 160 | +} |
| 161 | +``` |
| 162 | + |
| 163 | +Repositories? Also decorated. |
| 164 | +Controllers? Also decorated. |
| 165 | +Together, they form the Republic. |
| 166 | + |
| 167 | +GitHub Sample: [dirigiblelabs/sample-entity-decorators](https://github.com/dirigiblelabs/sample-entity-decorators) |
| 168 | + |
| 169 | +## Episode VI: Return of the Extensions |
| 170 | + |
| 171 | +Through the `@Extension` decorator, modules can add capabilities to others across the platform — like Jedi teachings passed between temples. |
| 172 | + |
| 173 | +```ts |
| 174 | +@Extension({ |
| 175 | + name: "OrderExtension", |
| 176 | + to: "order-extension-point" |
| 177 | +}) |
| 178 | +export class OrderExtension { |
| 179 | + public static getDiscount(): number { |
| 180 | + return 5; |
| 181 | + } |
| 182 | +} |
| 183 | +``` |
| 184 | + |
| 185 | +Other modules discover these extensions, aggregate them, and weave new logic. |
| 186 | + |
| 187 | +GitHub Sample: [dirigiblelabs/sample-extension-decorator](https://github.com/dirigiblelabs/sample-extension-decorator) |
| 188 | + |
| 189 | +## Episode VII: The Role Awakens |
| 190 | + |
| 191 | +Security is strong in this one. |
| 192 | + |
| 193 | +The `@Roles` decorator ensures only chosen users can access the protected paths of the application: |
| 194 | + |
| 195 | +```ts |
| 196 | +@Roles(["ADMINISTRATOR"]) |
| 197 | +class RolesCheck { |
| 198 | + public getMessage() { |
| 199 | + return { |
| 200 | + message: "Roles Check", |
| 201 | + user: user.getName(), |
| 202 | + date: new Date() |
| 203 | + }; |
| 204 | + } |
| 205 | +} |
| 206 | +``` |
| 207 | + |
| 208 | +Access control has never been more cinematic. |
| 209 | + |
| 210 | +GitHub Sample: [dirigiblelabs/sample-roles-decorator](https://github.com/dirigiblelabs/sample-roles-decorator) |
| 211 | + |
| 212 | +## Episode VIII: The Controller Menace |
| 213 | + |
| 214 | +HTTP controllers now join the decor family: |
| 215 | + |
| 216 | +* `@Controller` |
| 217 | +* `@Get` |
| 218 | +* `@Post` |
| 219 | +* `@Put` |
| 220 | +* `@Delete` |
| 221 | +* `@Documentation` |
| 222 | + |
| 223 | +A simple controller suddenly looks like a polished Jedi Master: |
| 224 | + |
| 225 | +```ts |
| 226 | +@Controller |
| 227 | +class CountryController { |
| 228 | + |
| 229 | + @Get("/") |
| 230 | + public getAll(): any[] { |
| 231 | + return this.countries; |
| 232 | + } |
| 233 | +} |
| 234 | +``` |
| 235 | + |
| 236 | +No friction. No config. No empire. |
| 237 | + |
| 238 | +## The Decorator Order is Here |
| 239 | + |
| 240 | +With the arrival of decorators in Eclipse Dirigible: |
| 241 | + |
| 242 | +* Dependency Injection becomes seamless |
| 243 | +* Jobs become declarative |
| 244 | +* Listeners become elegant |
| 245 | +* WebSockets become structured |
| 246 | +* Entities become readable |
| 247 | +* Extensions become modular |
| 248 | +* Roles become enforceable |
| 249 | +* Controllers become beautiful |
| 250 | + |
| 251 | +This is not an evolution. |
| 252 | +This is a Clone Army of productivity. |
| 253 | + |
| 254 | +The Attack of the Decorators is not an attack on the developer — it’s an attack on complexity. |
| 255 | +A battle we’re finally winning. |
| 256 | + |
| 257 | +May the Source be with you! |
0 commit comments