@tailor-platform/sdk 1.14.1 → 1.15.0

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +19 -0
  3. package/dist/{application-DnWZVbDO.mjs → application-DPunZ4lc.mjs} +95 -44
  4. package/dist/application-DPunZ4lc.mjs.map +1 -0
  5. package/dist/application-JwJ_-_PQ.mjs +4 -0
  6. package/dist/cli/index.mjs +5 -5
  7. package/dist/cli/lib.d.mts +62 -52
  8. package/dist/cli/lib.mjs +4 -4
  9. package/dist/cli/lib.mjs.map +1 -1
  10. package/dist/cli/skills.d.mts +2 -0
  11. package/dist/cli/skills.mjs +51 -0
  12. package/dist/cli/skills.mjs.map +1 -0
  13. package/dist/configure/index.d.mts +4 -4
  14. package/dist/configure/index.mjs +2 -9
  15. package/dist/configure/index.mjs.map +1 -1
  16. package/dist/{index-BlUBAAvu.d.mts → index-Bs9AsQb2.d.mts} +28 -11
  17. package/dist/index-DomkP6gz.d.mts +396 -0
  18. package/dist/{jiti-DuCiUfMj.mjs → jiti-BrELlEYT.mjs} +2 -2
  19. package/dist/{jiti-DuCiUfMj.mjs.map → jiti-BrELlEYT.mjs.map} +1 -1
  20. package/dist/{job-zGAXCidt.mjs → job-XiwGyFJt.mjs} +1 -1
  21. package/dist/{job-zGAXCidt.mjs.map → job-XiwGyFJt.mjs.map} +1 -1
  22. package/dist/plugin/index.d.mts +16 -2
  23. package/dist/plugin/index.mjs +208 -1
  24. package/dist/plugin/index.mjs.map +1 -1
  25. package/dist/{schema-BmKdDzr1.mjs → schema-DRYB-nzA.mjs} +1 -1
  26. package/dist/{schema-BmKdDzr1.mjs.map → schema-DRYB-nzA.mjs.map} +1 -1
  27. package/dist/{src-QNTCsO6J.mjs → src-DMROgdcL.mjs} +2 -2
  28. package/dist/{src-QNTCsO6J.mjs.map → src-DMROgdcL.mjs.map} +1 -1
  29. package/dist/{index-Bid18Opo.d.mts → types-Db1oxr0U.d.mts} +584 -509
  30. package/dist/{types-r-ZratAg.mjs → types-b-ig8nW_.mjs} +1 -1
  31. package/dist/types-b-ig8nW_.mjs.map +1 -0
  32. package/dist/{update-2eb6jz9o.mjs → update-C_ZTRB63.mjs} +419 -437
  33. package/dist/update-C_ZTRB63.mjs.map +1 -0
  34. package/dist/utils/test/index.d.mts +3 -3
  35. package/dist/utils/test/index.mjs +1 -1
  36. package/docs/plugin/custom.md +156 -83
  37. package/docs/plugin/index.md +2 -2
  38. package/package.json +5 -3
  39. package/skills/tailor-sdk/SKILL.md +34 -0
  40. package/dist/application-DM4zTgXU.mjs +0 -4
  41. package/dist/application-DnWZVbDO.mjs.map +0 -1
  42. package/dist/env-4RO7szrH.d.mts +0 -66
  43. package/dist/types-r-ZratAg.mjs.map +0 -1
  44. package/dist/update-2eb6jz9o.mjs.map +0 -1
  45. /package/dist/{chunk-C3Kl5s5P.mjs → chunk-GMkBE123.mjs} +0 -0
@@ -1,10 +1,10 @@
1
1
  /// <reference path="./../../user-defined.d.ts" />
2
- import { Ft as TailorField, rt as TailorDBType } from "../../index-Bid18Opo.mjs";
3
- import { G as WORKFLOW_TEST_ENV_KEY, n as output } from "../../index-BlUBAAvu.mjs";
2
+ import { M as TailorDBType, st as TailorField } from "../../types-Db1oxr0U.mjs";
3
+ import "../../index-DomkP6gz.mjs";
4
+ import { G as WORKFLOW_TEST_ENV_KEY, n as output } from "../../index-Bs9AsQb2.mjs";
4
5
  import { StandardSchemaV1 } from "@standard-schema/spec";
5
6
 
6
7
  //#region src/utils/test/index.d.ts
7
-
8
8
  /** Represents an unauthenticated user in the Tailor platform. */
9
9
  declare const unauthenticatedTailorUser: {
10
10
  readonly id: "00000000-0000-0000-0000-000000000000";
@@ -1,4 +1,4 @@
1
- import { t as WORKFLOW_TEST_ENV_KEY } from "../../job-zGAXCidt.mjs";
1
+ import { t as WORKFLOW_TEST_ENV_KEY } from "../../job-XiwGyFJt.mjs";
2
2
 
3
3
  //#region src/utils/test/index.ts
4
4
  /** Represents an unauthenticated user in the Tailor platform. */
@@ -2,12 +2,28 @@
2
2
 
3
3
  > **Beta Feature**: The custom plugin API is in beta and may change in future releases.
4
4
 
5
- Create your own plugins by implementing the `PluginBase` interface.
5
+ Create your own plugins by implementing the `Plugin` interface.
6
6
 
7
- ## PluginBase Interface
7
+ ## Requirements
8
+
9
+ **Plugins must use default export**:
8
10
 
9
11
  ```typescript
10
- interface PluginBase<PluginConfig = unknown> {
12
+ // plugin.ts
13
+ const myPlugin: Plugin = {
14
+ id: "@my-company/my-plugin",
15
+ // ...
16
+ };
17
+
18
+ export default myPlugin; // Required: must be default export
19
+ ```
20
+
21
+ This is required so that generators can use plugin-generated TailorDB types via `getGeneratedType()`.
22
+
23
+ ## Plugin Interface
24
+
25
+ ```typescript
26
+ interface Plugin<TypeConfig = unknown, PluginConfig = unknown> {
11
27
  /** Unique identifier for the plugin (e.g., "@my-company/soft-delete") */
12
28
  readonly id: string;
13
29
 
@@ -17,53 +33,46 @@ interface PluginBase<PluginConfig = unknown> {
17
33
  /** Import path for generated code to reference */
18
34
  readonly importPath: string;
19
35
 
20
- /** Schema for per-type configuration via .plugin() (required when using process) */
21
- readonly configSchema?: TailorAnyField;
22
-
23
- /** Schema for plugin-level configuration via definePlugins() (optional) */
24
- readonly pluginConfigSchema?: TailorAnyField;
25
-
26
36
  /** Controls whether per-type config is required when attaching via .plugin() */
27
37
  readonly typeConfigRequired?: boolean | ((pluginConfig?: PluginConfig) => boolean);
28
38
 
29
39
  /** Plugin-level config passed via definePlugins() */
30
40
  readonly pluginConfig?: PluginConfig;
31
41
 
32
- /** Optional template for generating PluginConfigs typing */
33
- readonly configTypeTemplate?: string;
34
-
35
42
  /** Process a type with this plugin attached */
36
- process?(context: PluginProcessContext): PluginOutput | Promise<PluginOutput>;
43
+ processType?(
44
+ context: PluginProcessContext<TypeConfig, PluginConfig>,
45
+ ): TypePluginOutput | Promise<TypePluginOutput>;
37
46
 
38
47
  /** Process a namespace (plugins without a source type) */
39
48
  processNamespace?(
40
- context: PluginNamespaceProcessContext,
41
- ): NamespacePluginOutput | Promise<NamespacePluginOutput>;
49
+ context: PluginNamespaceProcessContext<PluginConfig>,
50
+ ): PluginOutput | Promise<PluginOutput>;
42
51
  }
43
52
  ```
44
53
 
45
54
  Notes:
46
55
 
47
56
  - `importPath` should be resolvable from the directory containing `tailor.config.ts`. Code generators use it to import plugin APIs such as `getGeneratedType` and executor modules.
48
- - If you want to attach a plugin via `.plugin()`, you must provide `configSchema` and `process`.
49
- - Namespace-only plugins can omit `configSchema` and implement `processNamespace` instead.
50
- - `pluginConfig` stores the plugin-level config so it can be read later during processing. If you prefer not to set it manually, you can pass config as a tuple to `definePlugins([plugin, config])`.
51
- - For custom plugins, `pluginConfig` is the expected pattern. The tuple form can also be used to pass config.
57
+ - If you want to attach a plugin via `.plugin()`, implement the `processType` method.
58
+ - Namespace-only plugins implement `processNamespace` instead.
59
+ - `pluginConfig` stores the plugin-level config so it can be read later during processing. Set it on the plugin object (e.g., via a factory function) before passing to `definePlugins()`.
52
60
  - `resolve` should return a dynamic import; relative specifiers are resolved from the plugin module.
53
61
  - Per-type config is optional by default. Use `typeConfigRequired: true` to make it mandatory.
54
62
  - To toggle optional/required based on plugin config, provide a function for `typeConfigRequired`.
63
+ - Use TypeScript type parameters (`TypeConfig`, `PluginConfig`) to get type-safe config in your `processType` and `processNamespace` methods.
55
64
 
56
65
  ## PluginProcessContext
57
66
 
58
- Context passed to the `process` method:
67
+ Context passed to the `processType` method:
59
68
 
60
69
  ```typescript
61
- interface PluginProcessContext<Config = unknown, PluginConfig = unknown> {
70
+ interface PluginProcessContext<TypeConfig = unknown, PluginConfig = unknown> {
62
71
  /** The TailorDB type being processed */
63
72
  type: TailorAnyDBType;
64
73
 
65
- /** Per-type configuration from .plugin({ pluginId: config }) */
66
- config: Config;
74
+ /** Per-type configuration from .plugin({ pluginId: typeConfig }) */
75
+ typeConfig: TypeConfig;
67
76
 
68
77
  /** Plugin-level configuration from definePlugins() */
69
78
  pluginConfig: PluginConfig;
@@ -78,38 +87,20 @@ interface PluginProcessContext<Config = unknown, PluginConfig = unknown> {
78
87
  Context passed to the `processNamespace` method:
79
88
 
80
89
  ```typescript
81
- interface PluginNamespaceProcessContext<Config = unknown> {
90
+ interface PluginNamespaceProcessContext<PluginConfig = unknown> {
82
91
  /** Plugin-level configuration from definePlugins() */
83
- pluginConfig: Config;
92
+ pluginConfig: PluginConfig;
84
93
 
85
- /** Namespace of the TailorDB types */
94
+ /** Target namespace for generated types */
86
95
  namespace: string;
87
-
88
- /** TailorDB types in the namespace (after type-attached processing) */
89
- types: TailorAnyDBType[];
90
-
91
- /** Plugin-generated types for type-attached plugins in the namespace */
92
- generatedTypes: Array<{
93
- type: TailorAnyDBType;
94
- pluginId: string;
95
- generatedTypeKind?: string;
96
- originalType: TailorAnyDBType;
97
- }>;
98
96
  }
99
97
  ```
100
98
 
101
- `generatedTypes` includes only type-attached plugin-generated types (so `originalType` is always present), and `types` contains only user-defined types.
102
- For example:
99
+ ## Output Types
103
100
 
104
- ```typescript
105
- const changeRequestTypes = context.generatedTypes.filter(
106
- (entry) => entry.pluginId === "@example/change-request",
107
- );
108
- ```
109
-
110
- ## PluginOutput
101
+ ### PluginOutput (base)
111
102
 
112
- Return value from `process`:
103
+ Base output used by both `processType` and `processNamespace`:
113
104
 
114
105
  ```typescript
115
106
  interface PluginOutput {
@@ -121,19 +112,80 @@ interface PluginOutput {
121
112
 
122
113
  /** Additional executors to generate */
123
114
  executors?: PluginGeneratedExecutor[];
115
+ }
116
+ ```
117
+
118
+ ### TypePluginOutput
124
119
 
120
+ Return value from `processType`. Extends `PluginOutput` with the ability to add fields to the source type:
121
+
122
+ ```typescript
123
+ interface TypePluginOutput extends PluginOutput {
125
124
  /** Extensions to apply to the source type */
126
125
  extends?: {
127
126
  /** Fields to add to the source type */
128
- fields?: Record<string, TailorAnyField>;
127
+ fields?: Record<string, TailorAnyDBField>;
129
128
  };
130
129
  }
131
130
  ```
132
131
 
133
- `processNamespace` returns `NamespacePluginOutput` (same shape as `PluginOutput` but without `extends`):
132
+ `processNamespace` returns `PluginOutput` directly (namespace plugins cannot extend a source type).
133
+
134
+ ## getGeneratedType Helper
135
+
136
+ The SDK provides an async `getGeneratedType()` helper function to retrieve plugin-generated TailorDB types. This enables generators and other tools to work with types generated by plugins.
137
+
138
+ ```typescript
139
+ import { join } from "node:path";
140
+ import { getGeneratedType } from "@tailor-platform/sdk/plugin";
141
+ import { customer } from "./tailordb/customer";
142
+
143
+ const configPath = join(import.meta.dirname, "./tailor.config.ts");
144
+
145
+ // Get the generated type by config path, plugin ID, source type, and kind
146
+ const DeletedCustomer = await getGeneratedType(
147
+ configPath,
148
+ "@example/soft-delete",
149
+ customer,
150
+ "archive",
151
+ );
152
+ ```
153
+
154
+ **Parameters:**
155
+
156
+ - `configPath`: Path to `tailor.config.ts` (absolute or relative to cwd)
157
+ - `pluginId`: The plugin's unique identifier (e.g., `"@example/soft-delete"`)
158
+ - `sourceType`: The TailorDB type that the plugin is attached to (`null` for namespace plugins)
159
+ - `kind`: The generated type kind (e.g., `"archive"`, `"auditLog"`)
160
+
161
+ **How it works:**
162
+
163
+ 1. Loads and caches the config from the given path
164
+ 2. Finds the plugin by ID from `definePlugins()` exports
165
+ 3. Auto-resolves the namespace from config
166
+ 4. Calls the plugin's `processType()` or `processNamespace()` method
167
+ 5. Caches the result to avoid redundant processing
168
+ 6. Returns the generated type matching the specified kind
169
+
170
+ ### Example Usage
134
171
 
135
172
  ```typescript
136
- type NamespacePluginOutput = Omit<PluginOutput, "extends">;
173
+ import { join } from "node:path";
174
+ import { getGeneratedType } from "@tailor-platform/sdk/plugin";
175
+ import { customer } from "./tailordb/customer";
176
+
177
+ const configPath = join(import.meta.dirname, "./tailor.config.ts");
178
+
179
+ // Type-attached plugin
180
+ const DeletedCustomer = await getGeneratedType(
181
+ configPath,
182
+ "@example/soft-delete",
183
+ customer,
184
+ "archive",
185
+ );
186
+
187
+ // Namespace plugin (pass null as sourceType)
188
+ const AuditLog = await getGeneratedType(configPath, "@example/audit-log", null, "auditLog");
137
189
  ```
138
190
 
139
191
  ## Example: Soft Delete Plugin
@@ -144,8 +196,8 @@ A complete example of a plugin that adds soft delete functionality:
144
196
 
145
197
  ```typescript
146
198
  // plugins/soft-delete/plugin.ts
147
- import { db, t } from "@tailor-platform/sdk";
148
- import type { PluginBase, PluginProcessContext, PluginOutput } from "@tailor-platform/sdk";
199
+ import { db } from "@tailor-platform/sdk";
200
+ import type { Plugin, PluginProcessContext, TypePluginOutput } from "@tailor-platform/sdk";
149
201
 
150
202
  interface SoftDeleteConfig {
151
203
  archiveReason?: boolean;
@@ -158,23 +210,10 @@ interface SoftDeletePluginConfig {
158
210
  requireTypeConfig?: boolean;
159
211
  }
160
212
 
161
- const configSchema = t.object({
162
- archiveReason: t.bool({ optional: true }),
163
- retentionDays: t.int({ optional: true }),
164
- // Use { required: true } to mark fields as required in plugin configs.
165
- // By default, plugin config fields are optional.
166
- // token: t.string({ required: true }),
167
- });
168
-
169
- const pluginConfigSchema = t.object({
170
- archiveTablePrefix: t.string({ optional: true }),
171
- defaultRetentionDays: t.int({ optional: true }),
172
- });
173
-
174
213
  function processSoftDelete(
175
214
  context: PluginProcessContext<SoftDeleteConfig, SoftDeletePluginConfig>,
176
- ): PluginOutput {
177
- const { type, config, pluginConfig, namespace } = context;
215
+ ): TypePluginOutput {
216
+ const { type, typeConfig, pluginConfig, namespace } = context;
178
217
  const prefix = pluginConfig?.archiveTablePrefix ?? "Deleted_";
179
218
 
180
219
  // Generate archive type
@@ -184,7 +223,7 @@ function processSoftDelete(
184
223
  originalData: db.string().description("JSON snapshot of deleted record"),
185
224
  deletedAt: db.datetime().description("When the record was deleted"),
186
225
  deletedBy: db.uuid().description("User who deleted the record"),
187
- ...(config.archiveReason && {
226
+ ...(typeConfig.archiveReason && {
188
227
  reason: db.string({ optional: true }).description("Reason for deletion"),
189
228
  }),
190
229
  ...db.fields.timestamps(),
@@ -213,27 +252,31 @@ function processSoftDelete(
213
252
  };
214
253
  }
215
254
 
216
- // Factory function for plugins with namespace config
217
- export function softDeletePlugin(pluginConfig?: SoftDeletePluginConfig): PluginBase {
255
+ // Factory function for plugins with plugin-level config
256
+ function createSoftDeletePlugin(
257
+ pluginConfig?: SoftDeletePluginConfig,
258
+ ): Plugin<SoftDeleteConfig, SoftDeletePluginConfig> {
218
259
  return {
219
260
  id: "@example/soft-delete",
220
261
  description: "Adds soft delete with archive functionality",
221
262
  importPath: "./plugins/soft-delete",
222
- configSchema,
223
- pluginConfigSchema,
224
263
  pluginConfig,
225
264
  typeConfigRequired: (config) => config?.requireTypeConfig === true,
226
- process: processSoftDelete,
265
+ processType: processSoftDelete,
227
266
  };
228
267
  }
268
+
269
+ // Default export is required for getGeneratedType() to work
270
+ export default createSoftDeletePlugin();
229
271
  ```
230
272
 
231
273
  ### Executor with Context
232
274
 
233
275
  ```typescript
234
276
  // plugins/soft-delete/executors/on-delete.ts
235
- import { createExecutor, recordDeletedTrigger, withPluginContext } from "@tailor-platform/sdk";
277
+ import { createExecutor, recordDeletedTrigger } from "@tailor-platform/sdk";
236
278
  import type { TailorAnyDBType } from "@tailor-platform/sdk";
279
+ import { withPluginContext } from "@tailor-platform/sdk/plugin";
237
280
  import { getDB } from "generated/tailordb";
238
281
 
239
282
  interface SoftDeleteContext {
@@ -273,8 +316,9 @@ export default withPluginContext((ctx: SoftDeleteContext) => {
273
316
  ```typescript
274
317
  // tailor.config.ts
275
318
  import { definePlugins } from "@tailor-platform/sdk";
276
- import { softDeletePlugin } from "./plugins/soft-delete";
319
+ import softDeletePlugin from "./plugins/soft-delete";
277
320
 
321
+ // Use a factory function to pass plugin-level config
278
322
  export const plugins = definePlugins(
279
323
  softDeletePlugin({
280
324
  archiveTablePrefix: "Deleted_",
@@ -309,10 +353,39 @@ export const plugins = definePlugins(
309
353
 
310
354
  ## Adding Type Safety
311
355
 
312
- To enable type checking for your plugin's configuration, add a declaration merge:
356
+ Plugin type safety is provided at two levels:
357
+
358
+ ### Plugin-level type safety (TypeConfig / PluginConfig)
359
+
360
+ Use TypeScript type parameters on `Plugin<TypeConfig, PluginConfig>` to get type-safe config
361
+ in `processType` and `processNamespace` methods:
362
+
363
+ ```typescript
364
+ interface MyTypeConfig {
365
+ archiveReason?: boolean;
366
+ }
367
+
368
+ interface MyPluginConfig {
369
+ prefix?: string;
370
+ }
371
+
372
+ const plugin: Plugin<MyTypeConfig, MyPluginConfig> = {
373
+ id: "@example/my-plugin",
374
+ // ...
375
+ processType(context) {
376
+ // context.typeConfig is MyTypeConfig
377
+ // context.pluginConfig is MyPluginConfig
378
+ },
379
+ };
380
+ ```
381
+
382
+ ### Per-type `.plugin()` type safety (declaration merging)
383
+
384
+ To enable type checking when users attach plugins via `.plugin()`, provide a declaration merge
385
+ for the `PluginConfigs` interface. Plugin authors should ship this in their package's type definitions:
313
386
 
314
387
  ```typescript
315
- // user-defined.d.ts or your plugin's types.ts
388
+ // your-plugin/types.d.ts (shipped with your plugin package)
316
389
  declare module "@tailor-platform/sdk" {
317
390
  interface PluginConfigs<Fields extends string> {
318
391
  "@example/soft-delete": {
@@ -339,13 +412,13 @@ declare module "@tailor-platform/sdk" {
339
412
 
340
413
  ### Type-Attached Plugins
341
414
 
342
- Implement `process` to handle types with the plugin attached:
415
+ Implement `processType` to handle types with the plugin attached:
343
416
 
344
417
  ```typescript
345
- const plugin: PluginBase = {
418
+ const plugin: Plugin = {
346
419
  id: "@example/my-plugin",
347
420
  // ...
348
- process(context) {
421
+ processType(context) {
349
422
  // Called for each type with .plugin({ "@example/my-plugin": config })
350
423
  return {
351
424
  types: {
@@ -361,7 +434,7 @@ const plugin: PluginBase = {
361
434
  Implement `processNamespace` for plugins that generate types independently:
362
435
 
363
436
  ```typescript
364
- const plugin: PluginBase = {
437
+ const plugin: Plugin = {
365
438
  id: "@example/audit-log",
366
439
  // ...
367
440
  processNamespace(context) {
@@ -376,10 +449,10 @@ const plugin: PluginBase = {
376
449
  Implement both methods for plugins that support both modes:
377
450
 
378
451
  ```typescript
379
- const plugin: PluginBase = {
452
+ const plugin: Plugin = {
380
453
  id: "@example/hybrid",
381
454
  // ...
382
- process(context) {
455
+ processType(context) {
383
456
  // Handle type attachments
384
457
  },
385
458
  processNamespace(context) {
@@ -23,9 +23,9 @@ Define plugins in `tailor.config.ts` using `definePlugins()`:
23
23
 
24
24
  ```typescript
25
25
  import { defineConfig, definePlugins } from "@tailor-platform/sdk";
26
- import { myPlugin } from "./plugins/my-plugin";
26
+ import myPlugin from "./plugins/my-plugin";
27
27
 
28
- export const plugins = definePlugins(myPlugin());
28
+ export const plugins = definePlugins(myPlugin);
29
29
 
30
30
  export default defineConfig({
31
31
  name: "my-app",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk",
3
- "version": "1.14.1",
3
+ "version": "1.15.0",
4
4
  "description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -9,14 +9,16 @@
9
9
  "directory": "packages/sdk"
10
10
  },
11
11
  "bin": {
12
- "tailor-sdk": "./dist/cli/index.mjs"
12
+ "tailor-sdk": "./dist/cli/index.mjs",
13
+ "tailor-sdk-skills": "./dist/cli/skills.mjs"
13
14
  },
14
15
  "files": [
15
16
  "CHANGELOG.md",
16
17
  "dist",
17
18
  "docs",
18
19
  "postinstall.mjs",
19
- "README.md"
20
+ "README.md",
21
+ "skills"
20
22
  ],
21
23
  "type": "module",
22
24
  "main": "./dist/configure/index.mjs",
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: tailor-sdk
3
+ description: Use this skill when working with @tailor-platform/sdk projects, including service configuration, CLI usage, and docs navigation.
4
+ ---
5
+
6
+ # Tailor SDK Knowledge
7
+
8
+ This skill helps with projects using `@tailor-platform/sdk`.
9
+
10
+ ## Primary Sources
11
+
12
+ Use these files as the single source of truth:
13
+
14
+ - `node_modules/@tailor-platform/sdk/README.md`
15
+ - `node_modules/@tailor-platform/sdk/docs/configuration.md`
16
+ - `node_modules/@tailor-platform/sdk/docs/services/*.md`
17
+ - `node_modules/@tailor-platform/sdk/docs/cli-reference.md`
18
+ - `node_modules/@tailor-platform/sdk/docs/cli/*.md`
19
+ - `node_modules/@tailor-platform/sdk/docs/testing.md`
20
+
21
+ ## Working Rules
22
+
23
+ 1. Prefer SDK docs above assumptions. If behavior is unclear, cite the exact doc path used.
24
+ 2. Keep examples compatible with Node.js 22+.
25
+ 3. For CLI questions, verify command and option names from `docs/cli-reference.md` and `docs/cli/*.md`.
26
+ 4. For configuration questions, validate examples against `docs/configuration.md` and related service docs.
27
+
28
+ ## Quick Navigation
29
+
30
+ - Setup and first deploy: `docs/quickstart.md`
31
+ - Core config shape: `docs/configuration.md`
32
+ - Service details: `docs/services/*.md`
33
+ - CLI commands: `docs/cli-reference.md` and `docs/cli/*.md`
34
+ - Testing patterns: `docs/testing.md`
@@ -1,4 +0,0 @@
1
- import "./chunk-C3Kl5s5P.mjs";
2
- import { t as defineApplication } from "./application-DnWZVbDO.mjs";
3
-
4
- export { defineApplication };