@contractspec/example.saas-boilerplate 1.46.0 → 1.47.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 (131) hide show
  1. package/.turbo/turbo-build$colon$bundle.log +183 -108
  2. package/.turbo/turbo-build.log +182 -107
  3. package/CHANGELOG.md +58 -0
  4. package/README.md +0 -1
  5. package/dist/billing/billing.event.d.ts +4 -4
  6. package/dist/billing/billing.event.js +1 -1
  7. package/dist/billing/billing.operations.d.ts +5 -5
  8. package/dist/billing/billing.presentation.d.ts +3 -4
  9. package/dist/billing/billing.presentation.d.ts.map +1 -1
  10. package/dist/billing/billing.presentation.js +5 -5
  11. package/dist/billing/billing.presentation.js.map +1 -1
  12. package/dist/dashboard/dashboard.presentation.d.ts +3 -4
  13. package/dist/dashboard/dashboard.presentation.d.ts.map +1 -1
  14. package/dist/dashboard/dashboard.presentation.js +5 -5
  15. package/dist/dashboard/dashboard.presentation.js.map +1 -1
  16. package/dist/example.d.ts +2 -2
  17. package/dist/example.d.ts.map +1 -1
  18. package/dist/example.js +4 -2
  19. package/dist/example.js.map +1 -1
  20. package/dist/handlers/index.d.ts +2 -1
  21. package/dist/handlers/index.js +2 -1
  22. package/dist/handlers/saas.handlers.d.ts +68 -0
  23. package/dist/handlers/saas.handlers.d.ts.map +1 -0
  24. package/dist/handlers/saas.handlers.js +148 -0
  25. package/dist/handlers/saas.handlers.js.map +1 -0
  26. package/dist/index.d.ts +13 -1
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +13 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/project/project.event.d.ts +5 -5
  31. package/dist/project/project.event.d.ts.map +1 -1
  32. package/dist/project/project.event.js +1 -1
  33. package/dist/project/project.operations.d.ts +6 -6
  34. package/dist/project/project.presentation.d.ts +3 -4
  35. package/dist/project/project.presentation.d.ts.map +1 -1
  36. package/dist/project/project.presentation.js +5 -5
  37. package/dist/project/project.presentation.js.map +1 -1
  38. package/dist/saas-boilerplate.feature.d.ts +2 -2
  39. package/dist/saas-boilerplate.feature.d.ts.map +1 -1
  40. package/dist/saas-boilerplate.feature.js +9 -2
  41. package/dist/saas-boilerplate.feature.js.map +1 -1
  42. package/dist/seeders/index.d.ts +10 -0
  43. package/dist/seeders/index.d.ts.map +1 -0
  44. package/dist/seeders/index.js +19 -0
  45. package/dist/seeders/index.js.map +1 -0
  46. package/dist/shared/overlay-types.d.ts +34 -0
  47. package/dist/shared/overlay-types.d.ts.map +1 -0
  48. package/dist/shared/overlay-types.js +0 -0
  49. package/dist/tests/operations.test-spec.d.ts +10 -0
  50. package/dist/tests/operations.test-spec.d.ts.map +1 -0
  51. package/dist/tests/operations.test-spec.js +123 -0
  52. package/dist/tests/operations.test-spec.js.map +1 -0
  53. package/dist/ui/SaasDashboard.d.ts +7 -0
  54. package/dist/ui/SaasDashboard.d.ts.map +1 -0
  55. package/dist/ui/SaasDashboard.js +298 -0
  56. package/dist/ui/SaasDashboard.js.map +1 -0
  57. package/dist/ui/SaasProjectList.d.ts +14 -0
  58. package/dist/ui/SaasProjectList.d.ts.map +1 -0
  59. package/dist/ui/SaasProjectList.js +76 -0
  60. package/dist/ui/SaasProjectList.js.map +1 -0
  61. package/dist/ui/SaasSettingsPanel.d.ts +7 -0
  62. package/dist/ui/SaasSettingsPanel.d.ts.map +1 -0
  63. package/dist/ui/SaasSettingsPanel.js +138 -0
  64. package/dist/ui/SaasSettingsPanel.js.map +1 -0
  65. package/dist/ui/hooks/index.d.ts +3 -0
  66. package/dist/ui/hooks/index.js +6 -0
  67. package/dist/ui/hooks/useProjectList.d.ts +34 -0
  68. package/dist/ui/hooks/useProjectList.d.ts.map +1 -0
  69. package/dist/ui/hooks/useProjectList.js +75 -0
  70. package/dist/ui/hooks/useProjectList.js.map +1 -0
  71. package/dist/ui/hooks/useProjectMutations.d.ts +28 -0
  72. package/dist/ui/hooks/useProjectMutations.d.ts.map +1 -0
  73. package/dist/ui/hooks/useProjectMutations.js +146 -0
  74. package/dist/ui/hooks/useProjectMutations.js.map +1 -0
  75. package/dist/ui/index.d.ts +14 -0
  76. package/dist/ui/index.js +15 -0
  77. package/dist/ui/modals/CreateProjectModal.d.ts +23 -0
  78. package/dist/ui/modals/CreateProjectModal.d.ts.map +1 -0
  79. package/dist/ui/modals/CreateProjectModal.js +139 -0
  80. package/dist/ui/modals/CreateProjectModal.js.map +1 -0
  81. package/dist/ui/modals/ProjectActionsModal.d.ts +38 -0
  82. package/dist/ui/modals/ProjectActionsModal.d.ts.map +1 -0
  83. package/dist/ui/modals/ProjectActionsModal.js +292 -0
  84. package/dist/ui/modals/ProjectActionsModal.js.map +1 -0
  85. package/dist/ui/modals/index.d.ts +3 -0
  86. package/dist/ui/modals/index.js +4 -0
  87. package/dist/ui/overlays/demo-overlays.d.ts +19 -0
  88. package/dist/ui/overlays/demo-overlays.d.ts.map +1 -0
  89. package/dist/ui/overlays/demo-overlays.js +70 -0
  90. package/dist/ui/overlays/demo-overlays.js.map +1 -0
  91. package/dist/ui/overlays/index.d.ts +2 -0
  92. package/dist/ui/overlays/index.js +3 -0
  93. package/dist/ui/renderers/index.d.ts +3 -0
  94. package/dist/ui/renderers/index.js +4 -0
  95. package/dist/ui/renderers/project-list.markdown.d.ts +31 -0
  96. package/dist/ui/renderers/project-list.markdown.d.ts.map +1 -0
  97. package/dist/ui/renderers/project-list.markdown.js +148 -0
  98. package/dist/ui/renderers/project-list.markdown.js.map +1 -0
  99. package/dist/ui/renderers/project-list.renderer.d.ts +9 -0
  100. package/dist/ui/renderers/project-list.renderer.d.ts.map +1 -0
  101. package/dist/ui/renderers/project-list.renderer.js +17 -0
  102. package/dist/ui/renderers/project-list.renderer.js.map +1 -0
  103. package/package.json +38 -14
  104. package/src/billing/billing.presentation.ts +5 -6
  105. package/src/dashboard/dashboard.presentation.ts +5 -6
  106. package/src/example.ts +3 -3
  107. package/src/handlers/index.ts +3 -0
  108. package/src/handlers/saas.handlers.ts +300 -0
  109. package/src/index.ts +5 -0
  110. package/src/project/project.presentation.ts +5 -6
  111. package/src/saas-boilerplate.feature.ts +3 -3
  112. package/src/seeders/index.ts +28 -0
  113. package/src/shared/overlay-types.ts +39 -0
  114. package/src/tests/operations.test-spec.ts +109 -0
  115. package/src/ui/SaasDashboard.tsx +325 -0
  116. package/src/ui/SaasProjectList.tsx +113 -0
  117. package/src/ui/SaasSettingsPanel.tsx +96 -0
  118. package/src/ui/hooks/index.ts +10 -0
  119. package/src/ui/hooks/useProjectList.ts +95 -0
  120. package/src/ui/hooks/useProjectMutations.ts +166 -0
  121. package/src/ui/index.ts +18 -0
  122. package/src/ui/modals/CreateProjectModal.tsx +176 -0
  123. package/src/ui/modals/ProjectActionsModal.tsx +346 -0
  124. package/src/ui/modals/index.ts +2 -0
  125. package/src/ui/overlays/demo-overlays.ts +74 -0
  126. package/src/ui/overlays/index.ts +1 -0
  127. package/src/ui/renderers/index.ts +7 -0
  128. package/src/ui/renderers/project-list.markdown.ts +239 -0
  129. package/src/ui/renderers/project-list.renderer.tsx +22 -0
  130. package/tsconfig.json +1 -1
  131. package/tsconfig.tsbuildinfo +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"project.presentation.js","names":["ProjectListPresentation: PresentationSpec","ProjectDetailPresentation: PresentationSpec"],"sources":["../../src/project/project.presentation.ts"],"sourcesContent":["import type { PresentationSpec } from '@contractspec/lib.contracts';\nimport { StabilityEnum } from '@contractspec/lib.contracts';\nimport { ProjectModel } from './project.schema';\n\n/**\n * Presentation for displaying a list of projects.\n */\nexport const ProjectListPresentation: PresentationSpec = {\n meta: {\n key: 'saas.project.list',\n version: '1.0.0',\n title: 'Project List',\n description:\n 'List view of projects with status, tags, and last updated info',\n domain: 'saas-boilerplate',\n owners: ['@saas-team'],\n tags: ['project', 'list', 'dashboard'],\n stability: StabilityEnum.Beta,\n goal: 'Browse and manage projects',\n context: 'Project list page',\n },\n source: {\n type: 'component',\n framework: 'react',\n componentKey: 'ProjectListView',\n props: ProjectModel,\n },\n targets: ['react', 'markdown', 'application/json'],\n policy: {\n flags: ['saas.projects.enabled'],\n },\n};\n\n/**\n * Presentation for project detail view.\n */\nexport const ProjectDetailPresentation: PresentationSpec = {\n meta: {\n key: 'saas.project.detail',\n version: '1.0.0',\n title: 'Project Details',\n description: 'Detailed view of a project with settings and activity',\n domain: 'saas-boilerplate',\n owners: ['@saas-team'],\n tags: ['project', 'detail'],\n stability: StabilityEnum.Beta,\n goal: 'View and edit project details',\n context: 'Project detail page',\n },\n source: {\n type: 'component',\n framework: 'react',\n componentKey: 'ProjectDetailView',\n },\n targets: ['react', 'markdown'],\n policy: {\n flags: ['saas.projects.enabled'],\n },\n};\n"],"mappings":";;;;;;;AAOA,MAAaA,0BAA4C;CACvD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,aAAa;EACtB,MAAM;GAAC;GAAW;GAAQ;GAAY;EACtC,WAAW,cAAc;EACzB,MAAM;EACN,SAAS;EACV;CACD,QAAQ;EACN,MAAM;EACN,WAAW;EACX,cAAc;EACd,OAAO;EACR;CACD,SAAS;EAAC;EAAS;EAAY;EAAmB;CAClD,QAAQ,EACN,OAAO,CAAC,wBAAwB,EACjC;CACF;;;;AAKD,MAAaC,4BAA8C;CACzD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aAAa;EACb,QAAQ;EACR,QAAQ,CAAC,aAAa;EACtB,MAAM,CAAC,WAAW,SAAS;EAC3B,WAAW,cAAc;EACzB,MAAM;EACN,SAAS;EACV;CACD,QAAQ;EACN,MAAM;EACN,WAAW;EACX,cAAc;EACf;CACD,SAAS,CAAC,SAAS,WAAW;CAC9B,QAAQ,EACN,OAAO,CAAC,wBAAwB,EACjC;CACF"}
1
+ {"version":3,"file":"project.presentation.js","names":[],"sources":["../../src/project/project.presentation.ts"],"sourcesContent":["import { definePresentation, StabilityEnum } from '@contractspec/lib.contracts';\nimport { ProjectModel } from './project.schema';\n\n/**\n * Presentation for displaying a list of projects.\n */\nexport const ProjectListPresentation = definePresentation({\n meta: {\n key: 'saas.project.list',\n version: '1.0.0',\n title: 'Project List',\n description:\n 'List view of projects with status, tags, and last updated info',\n domain: 'saas-boilerplate',\n owners: ['@saas-team'],\n tags: ['project', 'list', 'dashboard'],\n stability: StabilityEnum.Beta,\n goal: 'Browse and manage projects',\n context: 'Project list page',\n },\n source: {\n type: 'component',\n framework: 'react',\n componentKey: 'ProjectListView',\n props: ProjectModel,\n },\n targets: ['react', 'markdown', 'application/json'],\n policy: {\n flags: ['saas.projects.enabled'],\n },\n});\n\n/**\n * Presentation for project detail view.\n */\nexport const ProjectDetailPresentation = definePresentation({\n meta: {\n key: 'saas.project.detail',\n version: '1.0.0',\n title: 'Project Details',\n description: 'Detailed view of a project with settings and activity',\n domain: 'saas-boilerplate',\n owners: ['@saas-team'],\n tags: ['project', 'detail'],\n stability: StabilityEnum.Beta,\n goal: 'View and edit project details',\n context: 'Project detail page',\n },\n source: {\n type: 'component',\n framework: 'react',\n componentKey: 'ProjectDetailView',\n },\n targets: ['react', 'markdown'],\n policy: {\n flags: ['saas.projects.enabled'],\n },\n});\n"],"mappings":";;;;;;;AAMA,MAAa,0BAA0B,mBAAmB;CACxD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,aAAa;EACtB,MAAM;GAAC;GAAW;GAAQ;GAAY;EACtC,WAAW,cAAc;EACzB,MAAM;EACN,SAAS;EACV;CACD,QAAQ;EACN,MAAM;EACN,WAAW;EACX,cAAc;EACd,OAAO;EACR;CACD,SAAS;EAAC;EAAS;EAAY;EAAmB;CAClD,QAAQ,EACN,OAAO,CAAC,wBAAwB,EACjC;CACF,CAAC;;;;AAKF,MAAa,4BAA4B,mBAAmB;CAC1D,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aAAa;EACb,QAAQ;EACR,QAAQ,CAAC,aAAa;EACtB,MAAM,CAAC,WAAW,SAAS;EAC3B,WAAW,cAAc;EACzB,MAAM;EACN,SAAS;EACV;CACD,QAAQ;EACN,MAAM;EACN,WAAW;EACX,cAAc;EACf;CACD,SAAS,CAAC,SAAS,WAAW;CAC9B,QAAQ,EACN,OAAO,CAAC,wBAAwB,EACjC;CACF,CAAC"}
@@ -1,4 +1,4 @@
1
- import { FeatureModuleSpec } from "@contractspec/lib.contracts";
1
+ import * as _contractspec_lib_contracts0 from "@contractspec/lib.contracts";
2
2
 
3
3
  //#region src/saas-boilerplate.feature.d.ts
4
4
 
@@ -6,7 +6,7 @@ import { FeatureModuleSpec } from "@contractspec/lib.contracts";
6
6
  * SaaS Boilerplate feature module that bundles project management,
7
7
  * billing, and settings operations into an installable feature.
8
8
  */
9
- declare const SaasBoilerplateFeature: FeatureModuleSpec;
9
+ declare const SaasBoilerplateFeature: _contractspec_lib_contracts0.FeatureModuleSpec;
10
10
  //#endregion
11
11
  export { SaasBoilerplateFeature };
12
12
  //# sourceMappingURL=saas-boilerplate.feature.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"saas-boilerplate.feature.d.ts","names":[],"sources":["../src/saas-boilerplate.feature.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAWa,wBAAwB"}
1
+ {"version":3,"file":"saas-boilerplate.feature.d.ts","names":[],"sources":["../src/saas-boilerplate.feature.ts"],"sourcesContent":[],"mappings":";;;;;;;AAWA;cAAa,wBAqGX,4BAAA,CArGiC"}
@@ -1,9 +1,16 @@
1
+ import { defineFeature } from "@contractspec/lib.contracts";
2
+
1
3
  //#region src/saas-boilerplate.feature.ts
2
4
  /**
5
+ * SaaS Boilerplate Feature Module Specification
6
+ *
7
+ * Defines the feature module for the SaaS application foundation.
8
+ */
9
+ /**
3
10
  * SaaS Boilerplate feature module that bundles project management,
4
11
  * billing, and settings operations into an installable feature.
5
12
  */
6
- const SaasBoilerplateFeature = {
13
+ const SaasBoilerplateFeature = defineFeature({
7
14
  meta: {
8
15
  key: "saas-boilerplate",
9
16
  title: "SaaS Boilerplate",
@@ -194,7 +201,7 @@ const SaasBoilerplateFeature = {
194
201
  version: "1.0.0"
195
202
  }
196
203
  ] }
197
- };
204
+ });
198
205
 
199
206
  //#endregion
200
207
  export { SaasBoilerplateFeature };
@@ -1 +1 @@
1
- {"version":3,"file":"saas-boilerplate.feature.js","names":["SaasBoilerplateFeature: FeatureModuleSpec"],"sources":["../src/saas-boilerplate.feature.ts"],"sourcesContent":["/**\n * SaaS Boilerplate Feature Module Specification\n *\n * Defines the feature module for the SaaS application foundation.\n */\nimport type { FeatureModuleSpec } from '@contractspec/lib.contracts';\n\n/**\n * SaaS Boilerplate feature module that bundles project management,\n * billing, and settings operations into an installable feature.\n */\nexport const SaasBoilerplateFeature: FeatureModuleSpec = {\n meta: {\n key: 'saas-boilerplate',\n title: 'SaaS Boilerplate',\n description:\n 'SaaS application foundation with projects, billing, and settings',\n domain: 'saas',\n owners: ['@saas-team'],\n tags: ['saas', 'projects', 'billing'],\n stability: 'experimental',\n version: '1.0.0',\n },\n\n // All contract operations included in this feature\n operations: [\n // Project operations\n { key: 'saas.project.create', version: '1.0.0' },\n { key: 'saas.project.get', version: '1.0.0' },\n { key: 'saas.project.update', version: '1.0.0' },\n { key: 'saas.project.delete', version: '1.0.0' },\n { key: 'saas.project.list', version: '1.0.0' },\n\n // Billing operations\n { key: 'saas.billing.subscription.get', version: '1.0.0' },\n { key: 'saas.billing.usage.record', version: '1.0.0' },\n { key: 'saas.billing.usage.summary', version: '1.0.0' },\n { key: 'saas.billing.feature.check', version: '1.0.0' },\n ],\n\n // Events emitted by this feature\n events: [\n // Project events\n { key: 'project.created', version: '1.0.0' },\n { key: 'project.updated', version: '1.0.0' },\n { key: 'project.deleted', version: '1.0.0' },\n { key: 'project.archived', version: '1.0.0' },\n\n // Billing events\n { key: 'billing.usage.recorded', version: '1.0.0' },\n { key: 'billing.subscription.changed', version: '1.0.0' },\n { key: 'billing.limit.reached', version: '1.0.0' },\n ],\n\n // Presentations associated with this feature\n presentations: [\n { key: 'saas.dashboard', version: '1.0.0' },\n { key: 'saas.project.list', version: '1.0.0' },\n { key: 'saas.project.detail', version: '1.0.0' },\n { key: 'saas.billing.subscription', version: '1.0.0' },\n { key: 'saas.billing.usage', version: '1.0.0' },\n { key: 'saas.settings', version: '1.0.0' },\n ],\n\n // Link operations to their primary presentations\n opToPresentation: [\n {\n op: { key: 'saas.project.list', version: '1.0.0' },\n pres: { key: 'saas.project.list', version: '1.0.0' },\n },\n {\n op: { key: 'saas.project.get', version: '1.0.0' },\n pres: { key: 'saas.project.detail', version: '1.0.0' },\n },\n {\n op: { key: 'saas.billing.subscription.get', version: '1.0.0' },\n pres: { key: 'saas.billing.subscription', version: '1.0.0' },\n },\n {\n op: { key: 'saas.billing.usage.summary', version: '1.0.0' },\n pres: { key: 'saas.billing.usage', version: '1.0.0' },\n },\n ],\n\n // Target requirements for multi-surface rendering\n presentationsTargets: [\n { key: 'saas.dashboard', version: '1.0.0', targets: ['react', 'markdown'] },\n {\n key: 'saas.project.list',\n version: '1.0.0',\n targets: ['react', 'markdown', 'application/json'],\n },\n {\n key: 'saas.billing.subscription',\n version: '1.0.0',\n targets: ['react', 'markdown'],\n },\n {\n key: 'saas.billing.usage',\n version: '1.0.0',\n targets: ['react', 'markdown'],\n },\n ],\n\n // Capability requirements\n capabilities: {\n requires: [\n { key: 'identity', version: '1.0.0' },\n { key: 'audit-trail', version: '1.0.0' },\n { key: 'notifications', version: '1.0.0' },\n ],\n },\n};\n"],"mappings":";;;;;AAWA,MAAaA,yBAA4C;CACvD,MAAM;EACJ,KAAK;EACL,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,aAAa;EACtB,MAAM;GAAC;GAAQ;GAAY;GAAU;EACrC,WAAW;EACX,SAAS;EACV;CAGD,YAAY;EAEV;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAoB,SAAS;GAAS;EAC7C;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAqB,SAAS;GAAS;EAG9C;GAAE,KAAK;GAAiC,SAAS;GAAS;EAC1D;GAAE,KAAK;GAA6B,SAAS;GAAS;EACtD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACvD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACxD;CAGD,QAAQ;EAEN;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAoB,SAAS;GAAS;EAG7C;GAAE,KAAK;GAA0B,SAAS;GAAS;EACnD;GAAE,KAAK;GAAgC,SAAS;GAAS;EACzD;GAAE,KAAK;GAAyB,SAAS;GAAS;EACnD;CAGD,eAAe;EACb;GAAE,KAAK;GAAkB,SAAS;GAAS;EAC3C;GAAE,KAAK;GAAqB,SAAS;GAAS;EAC9C;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAA6B,SAAS;GAAS;EACtD;GAAE,KAAK;GAAsB,SAAS;GAAS;EAC/C;GAAE,KAAK;GAAiB,SAAS;GAAS;EAC3C;CAGD,kBAAkB;EAChB;GACE,IAAI;IAAE,KAAK;IAAqB,SAAS;IAAS;GAClD,MAAM;IAAE,KAAK;IAAqB,SAAS;IAAS;GACrD;EACD;GACE,IAAI;IAAE,KAAK;IAAoB,SAAS;IAAS;GACjD,MAAM;IAAE,KAAK;IAAuB,SAAS;IAAS;GACvD;EACD;GACE,IAAI;IAAE,KAAK;IAAiC,SAAS;IAAS;GAC9D,MAAM;IAAE,KAAK;IAA6B,SAAS;IAAS;GAC7D;EACD;GACE,IAAI;IAAE,KAAK;IAA8B,SAAS;IAAS;GAC3D,MAAM;IAAE,KAAK;IAAsB,SAAS;IAAS;GACtD;EACF;CAGD,sBAAsB;EACpB;GAAE,KAAK;GAAkB,SAAS;GAAS,SAAS,CAAC,SAAS,WAAW;GAAE;EAC3E;GACE,KAAK;GACL,SAAS;GACT,SAAS;IAAC;IAAS;IAAY;IAAmB;GACnD;EACD;GACE,KAAK;GACL,SAAS;GACT,SAAS,CAAC,SAAS,WAAW;GAC/B;EACD;GACE,KAAK;GACL,SAAS;GACT,SAAS,CAAC,SAAS,WAAW;GAC/B;EACF;CAGD,cAAc,EACZ,UAAU;EACR;GAAE,KAAK;GAAY,SAAS;GAAS;EACrC;GAAE,KAAK;GAAe,SAAS;GAAS;EACxC;GAAE,KAAK;GAAiB,SAAS;GAAS;EAC3C,EACF;CACF"}
1
+ {"version":3,"file":"saas-boilerplate.feature.js","names":[],"sources":["../src/saas-boilerplate.feature.ts"],"sourcesContent":["/**\n * SaaS Boilerplate Feature Module Specification\n *\n * Defines the feature module for the SaaS application foundation.\n */\nimport { defineFeature } from '@contractspec/lib.contracts';\n\n/**\n * SaaS Boilerplate feature module that bundles project management,\n * billing, and settings operations into an installable feature.\n */\nexport const SaasBoilerplateFeature = defineFeature({\n meta: {\n key: 'saas-boilerplate',\n title: 'SaaS Boilerplate',\n description:\n 'SaaS application foundation with projects, billing, and settings',\n domain: 'saas',\n owners: ['@saas-team'],\n tags: ['saas', 'projects', 'billing'],\n stability: 'experimental',\n version: '1.0.0',\n },\n\n // All contract operations included in this feature\n operations: [\n // Project operations\n { key: 'saas.project.create', version: '1.0.0' },\n { key: 'saas.project.get', version: '1.0.0' },\n { key: 'saas.project.update', version: '1.0.0' },\n { key: 'saas.project.delete', version: '1.0.0' },\n { key: 'saas.project.list', version: '1.0.0' },\n\n // Billing operations\n { key: 'saas.billing.subscription.get', version: '1.0.0' },\n { key: 'saas.billing.usage.record', version: '1.0.0' },\n { key: 'saas.billing.usage.summary', version: '1.0.0' },\n { key: 'saas.billing.feature.check', version: '1.0.0' },\n ],\n\n // Events emitted by this feature\n events: [\n // Project events\n { key: 'project.created', version: '1.0.0' },\n { key: 'project.updated', version: '1.0.0' },\n { key: 'project.deleted', version: '1.0.0' },\n { key: 'project.archived', version: '1.0.0' },\n\n // Billing events\n { key: 'billing.usage.recorded', version: '1.0.0' },\n { key: 'billing.subscription.changed', version: '1.0.0' },\n { key: 'billing.limit.reached', version: '1.0.0' },\n ],\n\n // Presentations associated with this feature\n presentations: [\n { key: 'saas.dashboard', version: '1.0.0' },\n { key: 'saas.project.list', version: '1.0.0' },\n { key: 'saas.project.detail', version: '1.0.0' },\n { key: 'saas.billing.subscription', version: '1.0.0' },\n { key: 'saas.billing.usage', version: '1.0.0' },\n { key: 'saas.settings', version: '1.0.0' },\n ],\n\n // Link operations to their primary presentations\n opToPresentation: [\n {\n op: { key: 'saas.project.list', version: '1.0.0' },\n pres: { key: 'saas.project.list', version: '1.0.0' },\n },\n {\n op: { key: 'saas.project.get', version: '1.0.0' },\n pres: { key: 'saas.project.detail', version: '1.0.0' },\n },\n {\n op: { key: 'saas.billing.subscription.get', version: '1.0.0' },\n pres: { key: 'saas.billing.subscription', version: '1.0.0' },\n },\n {\n op: { key: 'saas.billing.usage.summary', version: '1.0.0' },\n pres: { key: 'saas.billing.usage', version: '1.0.0' },\n },\n ],\n\n // Target requirements for multi-surface rendering\n presentationsTargets: [\n { key: 'saas.dashboard', version: '1.0.0', targets: ['react', 'markdown'] },\n {\n key: 'saas.project.list',\n version: '1.0.0',\n targets: ['react', 'markdown', 'application/json'],\n },\n {\n key: 'saas.billing.subscription',\n version: '1.0.0',\n targets: ['react', 'markdown'],\n },\n {\n key: 'saas.billing.usage',\n version: '1.0.0',\n targets: ['react', 'markdown'],\n },\n ],\n\n // Capability requirements\n capabilities: {\n requires: [\n { key: 'identity', version: '1.0.0' },\n { key: 'audit-trail', version: '1.0.0' },\n { key: 'notifications', version: '1.0.0' },\n ],\n },\n});\n"],"mappings":";;;;;;;;;;;;AAWA,MAAa,yBAAyB,cAAc;CAClD,MAAM;EACJ,KAAK;EACL,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,aAAa;EACtB,MAAM;GAAC;GAAQ;GAAY;GAAU;EACrC,WAAW;EACX,SAAS;EACV;CAGD,YAAY;EAEV;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAoB,SAAS;GAAS;EAC7C;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAAqB,SAAS;GAAS;EAG9C;GAAE,KAAK;GAAiC,SAAS;GAAS;EAC1D;GAAE,KAAK;GAA6B,SAAS;GAAS;EACtD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACvD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACxD;CAGD,QAAQ;EAEN;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAmB,SAAS;GAAS;EAC5C;GAAE,KAAK;GAAoB,SAAS;GAAS;EAG7C;GAAE,KAAK;GAA0B,SAAS;GAAS;EACnD;GAAE,KAAK;GAAgC,SAAS;GAAS;EACzD;GAAE,KAAK;GAAyB,SAAS;GAAS;EACnD;CAGD,eAAe;EACb;GAAE,KAAK;GAAkB,SAAS;GAAS;EAC3C;GAAE,KAAK;GAAqB,SAAS;GAAS;EAC9C;GAAE,KAAK;GAAuB,SAAS;GAAS;EAChD;GAAE,KAAK;GAA6B,SAAS;GAAS;EACtD;GAAE,KAAK;GAAsB,SAAS;GAAS;EAC/C;GAAE,KAAK;GAAiB,SAAS;GAAS;EAC3C;CAGD,kBAAkB;EAChB;GACE,IAAI;IAAE,KAAK;IAAqB,SAAS;IAAS;GAClD,MAAM;IAAE,KAAK;IAAqB,SAAS;IAAS;GACrD;EACD;GACE,IAAI;IAAE,KAAK;IAAoB,SAAS;IAAS;GACjD,MAAM;IAAE,KAAK;IAAuB,SAAS;IAAS;GACvD;EACD;GACE,IAAI;IAAE,KAAK;IAAiC,SAAS;IAAS;GAC9D,MAAM;IAAE,KAAK;IAA6B,SAAS;IAAS;GAC7D;EACD;GACE,IAAI;IAAE,KAAK;IAA8B,SAAS;IAAS;GAC3D,MAAM;IAAE,KAAK;IAAsB,SAAS;IAAS;GACtD;EACF;CAGD,sBAAsB;EACpB;GAAE,KAAK;GAAkB,SAAS;GAAS,SAAS,CAAC,SAAS,WAAW;GAAE;EAC3E;GACE,KAAK;GACL,SAAS;GACT,SAAS;IAAC;IAAS;IAAY;IAAmB;GACnD;EACD;GACE,KAAK;GACL,SAAS;GACT,SAAS,CAAC,SAAS,WAAW;GAC/B;EACD;GACE,KAAK;GACL,SAAS;GACT,SAAS,CAAC,SAAS,WAAW;GAC/B;EACF;CAGD,cAAc,EACZ,UAAU;EACR;GAAE,KAAK;GAAY,SAAS;GAAS;EACrC;GAAE,KAAK;GAAe,SAAS;GAAS;EACxC;GAAE,KAAK;GAAiB,SAAS;GAAS;EAC3C,EACF;CACF,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { DatabasePort } from "@contractspec/lib.runtime-sandbox";
2
+
3
+ //#region src/seeders/index.d.ts
4
+ declare function seedSaasBoilerplate(params: {
5
+ projectId: string;
6
+ db: DatabasePort;
7
+ }): Promise<void>;
8
+ //#endregion
9
+ export { seedSaasBoilerplate };
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/seeders/index.ts"],"sourcesContent":[],"mappings":";;;iBAEsB,mBAAA;;EAAA,EAAA,EAEhB,YAFgB;IAGrB"}
@@ -0,0 +1,19 @@
1
+ //#region src/seeders/index.ts
2
+ async function seedSaasBoilerplate(params) {
3
+ const { projectId, db } = params;
4
+ if ((await db.query(`SELECT COUNT(*) as count FROM saas_project WHERE "projectId" = $1`, [projectId])).rows[0]?.count > 0) return;
5
+ await db.execute(`INSERT INTO saas_project (id, "projectId", "organizationId", name, description, status, tier)
6
+ VALUES ($1, $2, $3, $4, $5, $6, $7)`, [
7
+ "saas_proj_1",
8
+ projectId,
9
+ "org_demo",
10
+ "Demo Project",
11
+ "A demo SaaS project",
12
+ "ACTIVE",
13
+ "PRO"
14
+ ]);
15
+ }
16
+
17
+ //#endregion
18
+ export { seedSaasBoilerplate };
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/seeders/index.ts"],"sourcesContent":["import type { DatabasePort } from '@contractspec/lib.runtime-sandbox';\n\nexport async function seedSaasBoilerplate(params: {\n projectId: string;\n db: DatabasePort;\n}) {\n const { projectId, db } = params;\n\n const existing = await db.query(\n `SELECT COUNT(*) as count FROM saas_project WHERE \"projectId\" = $1`,\n [projectId]\n );\n if ((existing.rows[0]?.count as number) > 0) return;\n\n await db.execute(\n `INSERT INTO saas_project (id, \"projectId\", \"organizationId\", name, description, status, tier)\n VALUES ($1, $2, $3, $4, $5, $6, $7)`,\n [\n 'saas_proj_1',\n projectId,\n 'org_demo',\n 'Demo Project',\n 'A demo SaaS project',\n 'ACTIVE',\n 'PRO',\n ]\n );\n}\n"],"mappings":";AAEA,eAAsB,oBAAoB,QAGvC;CACD,MAAM,EAAE,WAAW,OAAO;AAM1B,MAJiB,MAAM,GAAG,MACxB,qEACA,CAAC,UAAU,CACZ,EACa,KAAK,IAAI,QAAmB,EAAG;AAE7C,OAAM,GAAG,QACP;2CAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF"}
@@ -0,0 +1,34 @@
1
+ //#region src/shared/overlay-types.d.ts
2
+ interface OverlayDefinition {
3
+ overlayId: string;
4
+ version: string;
5
+ description: string;
6
+ appliesTo: Record<string, string>;
7
+ modifications: OverlayModification[];
8
+ }
9
+ type OverlayModification = HideFieldModification | RenameLabelModification | AddBadgeModification | SetLimitModification;
10
+ interface HideFieldModification {
11
+ type: 'hideField';
12
+ field: string;
13
+ reason?: string;
14
+ }
15
+ interface RenameLabelModification {
16
+ type: 'renameLabel';
17
+ field: string;
18
+ newLabel: string;
19
+ }
20
+ interface AddBadgeModification {
21
+ type: 'addBadge';
22
+ position: 'header' | 'footer';
23
+ label: string;
24
+ variant: 'warning' | 'info' | 'error' | 'success' | 'default';
25
+ }
26
+ interface SetLimitModification {
27
+ type: 'setLimit';
28
+ field: string;
29
+ max: number;
30
+ message: string;
31
+ }
32
+ //#endregion
33
+ export { AddBadgeModification, HideFieldModification, OverlayDefinition, OverlayModification, RenameLabelModification, SetLimitModification };
34
+ //# sourceMappingURL=overlay-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"overlay-types.d.ts","names":[],"sources":["../../src/shared/overlay-types.ts"],"sourcesContent":[],"mappings":";UAAiB,iBAAA;EAAA,SAAA,EAAA,MAAA;EAQL,OAAA,EAAA,MAAA;EACR,WAAA,EAAA,MAAA;EACA,SAAA,EANS,MAMT,CAAA,MAAA,EAAA,MAAA,CAAA;EACA,aAAA,EANa,mBAMb,EAAA;;AACoB,KAJZ,mBAAA,GACR,qBAGoB,GAFpB,uBAEoB,GADpB,oBACoB,GAApB,oBAAoB;AAEP,UAAA,qBAAA,CAAqB;EAMrB,IAAA,EAAA,WAAA;EAMA,KAAA,EAAA,MAAA;EAOA,MAAA,CAAA,EAAA,MAAA;;UAbA,uBAAA;;;;;UAMA,oBAAA;;;;;;UAOA,oBAAA"}
File without changes
@@ -0,0 +1,10 @@
1
+ import * as _contractspec_lib_contracts23 from "@contractspec/lib.contracts";
2
+
3
+ //#region src/tests/operations.test-spec.d.ts
4
+ declare const ProjectListTest: _contractspec_lib_contracts23.TestSpec;
5
+ declare const ProjectGetTest: _contractspec_lib_contracts23.TestSpec;
6
+ declare const BillingSubscriptionGetTest: _contractspec_lib_contracts23.TestSpec;
7
+ declare const BillingUsageSummaryTest: _contractspec_lib_contracts23.TestSpec;
8
+ //#endregion
9
+ export { BillingSubscriptionGetTest, BillingUsageSummaryTest, ProjectGetTest, ProjectListTest };
10
+ //# sourceMappingURL=operations.test-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.test-spec.d.ts","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":[],"mappings":";;;cAEa,iBAyBX,6BAAA,CAzB0B;cA2Bf,gBAyBX,6BAAA,CAzByB;cA2Bd,4BAyBX,6BAAA,CAzBqC;AAtD1B,cAiFA,uBAxDX,EAiFA,6BAAA,CAzBkC,QAxDlC"}
@@ -0,0 +1,123 @@
1
+ import { defineTestSpec } from "@contractspec/lib.contracts";
2
+
3
+ //#region src/tests/operations.test-spec.ts
4
+ const ProjectListTest = defineTestSpec({
5
+ meta: {
6
+ key: "saas.project.list.test",
7
+ version: "1.0.0",
8
+ stability: "experimental",
9
+ owners: ["@example.saas-boilerplate"],
10
+ description: "Test for listing projects",
11
+ tags: ["test"]
12
+ },
13
+ target: {
14
+ type: "operation",
15
+ operation: {
16
+ key: "saas.project.list",
17
+ version: "1.0.0"
18
+ }
19
+ },
20
+ scenarios: [{
21
+ key: "success",
22
+ when: { operation: { key: "saas.project.list" } },
23
+ then: [{
24
+ type: "expectOutput",
25
+ match: {}
26
+ }]
27
+ }, {
28
+ key: "error",
29
+ when: { operation: { key: "saas.project.list" } },
30
+ then: [{ type: "expectError" }]
31
+ }]
32
+ });
33
+ const ProjectGetTest = defineTestSpec({
34
+ meta: {
35
+ key: "saas.project.get.test",
36
+ version: "1.0.0",
37
+ stability: "experimental",
38
+ owners: ["@example.saas-boilerplate"],
39
+ description: "Test for getting project",
40
+ tags: ["test"]
41
+ },
42
+ target: {
43
+ type: "operation",
44
+ operation: {
45
+ key: "saas.project.get",
46
+ version: "1.0.0"
47
+ }
48
+ },
49
+ scenarios: [{
50
+ key: "success",
51
+ when: { operation: { key: "saas.project.get" } },
52
+ then: [{
53
+ type: "expectOutput",
54
+ match: {}
55
+ }]
56
+ }, {
57
+ key: "error",
58
+ when: { operation: { key: "saas.project.get" } },
59
+ then: [{ type: "expectError" }]
60
+ }]
61
+ });
62
+ const BillingSubscriptionGetTest = defineTestSpec({
63
+ meta: {
64
+ key: "saas.billing.subscription.get.test",
65
+ version: "1.0.0",
66
+ stability: "experimental",
67
+ owners: ["@example.saas-boilerplate"],
68
+ description: "Test for getting subscription",
69
+ tags: ["test"]
70
+ },
71
+ target: {
72
+ type: "operation",
73
+ operation: {
74
+ key: "saas.billing.subscription.get",
75
+ version: "1.0.0"
76
+ }
77
+ },
78
+ scenarios: [{
79
+ key: "success",
80
+ when: { operation: { key: "saas.billing.subscription.get" } },
81
+ then: [{
82
+ type: "expectOutput",
83
+ match: {}
84
+ }]
85
+ }, {
86
+ key: "error",
87
+ when: { operation: { key: "saas.billing.subscription.get" } },
88
+ then: [{ type: "expectError" }]
89
+ }]
90
+ });
91
+ const BillingUsageSummaryTest = defineTestSpec({
92
+ meta: {
93
+ key: "saas.billing.usage.summary.test",
94
+ version: "1.0.0",
95
+ stability: "experimental",
96
+ owners: ["@example.saas-boilerplate"],
97
+ description: "Test for getting usage summary",
98
+ tags: ["test"]
99
+ },
100
+ target: {
101
+ type: "operation",
102
+ operation: {
103
+ key: "saas.billing.usage.summary",
104
+ version: "1.0.0"
105
+ }
106
+ },
107
+ scenarios: [{
108
+ key: "success",
109
+ when: { operation: { key: "saas.billing.usage.summary" } },
110
+ then: [{
111
+ type: "expectOutput",
112
+ match: {}
113
+ }]
114
+ }, {
115
+ key: "error",
116
+ when: { operation: { key: "saas.billing.usage.summary" } },
117
+ then: [{ type: "expectError" }]
118
+ }]
119
+ });
120
+
121
+ //#endregion
122
+ export { BillingSubscriptionGetTest, BillingUsageSummaryTest, ProjectGetTest, ProjectListTest };
123
+ //# sourceMappingURL=operations.test-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.test-spec.js","names":[],"sources":["../../src/tests/operations.test-spec.ts"],"sourcesContent":["import { defineTestSpec } from '@contractspec/lib.contracts';\n\nexport const ProjectListTest = defineTestSpec({\n meta: {\n key: 'saas.project.list.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.saas-boilerplate'],\n description: 'Test for listing projects',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'saas.project.list', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'saas.project.list' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'saas.project.list' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const ProjectGetTest = defineTestSpec({\n meta: {\n key: 'saas.project.get.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.saas-boilerplate'],\n description: 'Test for getting project',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'saas.project.get', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'saas.project.get' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'saas.project.get' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const BillingSubscriptionGetTest = defineTestSpec({\n meta: {\n key: 'saas.billing.subscription.get.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.saas-boilerplate'],\n description: 'Test for getting subscription',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'saas.billing.subscription.get', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'saas.billing.subscription.get' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'saas.billing.subscription.get' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n\nexport const BillingUsageSummaryTest = defineTestSpec({\n meta: {\n key: 'saas.billing.usage.summary.test',\n version: '1.0.0',\n stability: 'experimental',\n owners: ['@example.saas-boilerplate'],\n description: 'Test for getting usage summary',\n tags: ['test'],\n },\n target: {\n type: 'operation',\n operation: { key: 'saas.billing.usage.summary', version: '1.0.0' },\n },\n scenarios: [\n {\n key: 'success',\n when: { operation: { key: 'saas.billing.usage.summary' } },\n then: [{ type: 'expectOutput', match: {} }],\n },\n {\n key: 'error',\n when: { operation: { key: 'saas.billing.usage.summary' } },\n then: [{ type: 'expectError' }],\n },\n ],\n});\n"],"mappings":";;;AAEA,MAAa,kBAAkB,eAAe;CAC5C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,4BAA4B;EACrC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAqB,SAAS;GAAS;EAC1D;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,qBAAqB,EAAE;EACjD,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,qBAAqB,EAAE;EACjD,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,iBAAiB,eAAe;CAC3C,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,4BAA4B;EACrC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAoB,SAAS;GAAS;EACzD;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,oBAAoB,EAAE;EAChD,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,oBAAoB,EAAE;EAChD,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,6BAA6B,eAAe;CACvD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,4BAA4B;EACrC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAAiC,SAAS;GAAS;EACtE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,iCAAiC,EAAE;EAC7D,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,iCAAiC,EAAE;EAC7D,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC;AAEF,MAAa,0BAA0B,eAAe;CACpD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,WAAW;EACX,QAAQ,CAAC,4BAA4B;EACrC,aAAa;EACb,MAAM,CAAC,OAAO;EACf;CACD,QAAQ;EACN,MAAM;EACN,WAAW;GAAE,KAAK;GAA8B,SAAS;GAAS;EACnE;CACD,WAAW,CACT;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,8BAA8B,EAAE;EAC1D,MAAM,CAAC;GAAE,MAAM;GAAgB,OAAO,EAAE;GAAE,CAAC;EAC5C,EACD;EACE,KAAK;EACL,MAAM,EAAE,WAAW,EAAE,KAAK,8BAA8B,EAAE;EAC1D,MAAM,CAAC,EAAE,MAAM,eAAe,CAAC;EAChC,CACF;CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+
3
+ //#region src/ui/SaasDashboard.d.ts
4
+ declare function SaasDashboard(): react_jsx_runtime0.JSX.Element;
5
+ //#endregion
6
+ export { SaasDashboard };
7
+ //# sourceMappingURL=SaasDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SaasDashboard.d.ts","names":[],"sources":["../../src/ui/SaasDashboard.tsx"],"sourcesContent":[],"mappings":";;;iBAkDgB,aAAA,CAAA,GAAa,kBAAA,CAAA,GAAA,CAAA"}
@@ -0,0 +1,298 @@
1
+ 'use client';
2
+
3
+ import { useProjectList } from "./hooks/useProjectList.js";
4
+ import { useProjectMutations } from "./hooks/useProjectMutations.js";
5
+ import { CreateProjectModal } from "./modals/CreateProjectModal.js";
6
+ import { ProjectActionsModal } from "./modals/ProjectActionsModal.js";
7
+ import { useCallback, useState } from "react";
8
+ import { Button, EmptyState, EntityCard, ErrorState, LoaderBlock, StatCard, StatCardGroup, StatusChip } from "@contractspec/lib.design-system";
9
+ import { jsx, jsxs } from "react/jsx-runtime";
10
+
11
+ //#region src/ui/SaasDashboard.tsx
12
+ /**
13
+ * SaaS Dashboard
14
+ *
15
+ * Fully integrated with ContractSpec example handlers
16
+ * and design-system components.
17
+ *
18
+ * Commands wired:
19
+ * - CreateProjectContract -> Create Project button + modal
20
+ * - UpdateProjectContract -> Edit project via modal
21
+ * - DeleteProjectContract -> Delete project via modal
22
+ */
23
+ function getStatusTone(status) {
24
+ switch (status) {
25
+ case "ACTIVE": return "success";
26
+ case "DRAFT": return "neutral";
27
+ case "ARCHIVED": return "warning";
28
+ default: return "neutral";
29
+ }
30
+ }
31
+ function SaasDashboard() {
32
+ const [activeTab, setActiveTab] = useState("projects");
33
+ const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
34
+ const [selectedProject, setSelectedProject] = useState(null);
35
+ const [isProjectActionsOpen, setIsProjectActionsOpen] = useState(false);
36
+ const { data, subscription, loading, error, stats, refetch } = useProjectList();
37
+ const mutations = useProjectMutations({ onSuccess: () => {
38
+ refetch();
39
+ } });
40
+ const handleProjectClick = useCallback((project) => {
41
+ setSelectedProject(project);
42
+ setIsProjectActionsOpen(true);
43
+ }, []);
44
+ const tabs = [
45
+ {
46
+ id: "projects",
47
+ label: "Projects",
48
+ icon: "📁"
49
+ },
50
+ {
51
+ id: "billing",
52
+ label: "Billing",
53
+ icon: "💳"
54
+ },
55
+ {
56
+ id: "settings",
57
+ label: "Settings",
58
+ icon: "⚙️"
59
+ }
60
+ ];
61
+ if (loading && !data) return /* @__PURE__ */ jsx(LoaderBlock, { label: "Loading dashboard..." });
62
+ if (error) return /* @__PURE__ */ jsx(ErrorState, {
63
+ title: "Failed to load dashboard",
64
+ description: error.message,
65
+ onRetry: refetch,
66
+ retryLabel: "Retry"
67
+ });
68
+ return /* @__PURE__ */ jsxs("div", {
69
+ className: "space-y-6",
70
+ children: [
71
+ /* @__PURE__ */ jsxs("div", {
72
+ className: "flex items-center justify-between",
73
+ children: [/* @__PURE__ */ jsx("h2", {
74
+ className: "text-2xl font-bold",
75
+ children: "SaaS Dashboard"
76
+ }), activeTab === "projects" && /* @__PURE__ */ jsxs(Button, {
77
+ onPress: () => setIsCreateModalOpen(true),
78
+ children: [/* @__PURE__ */ jsx("span", {
79
+ className: "mr-2",
80
+ children: "+"
81
+ }), " New Project"]
82
+ })]
83
+ }),
84
+ stats && subscription && /* @__PURE__ */ jsxs(StatCardGroup, { children: [
85
+ /* @__PURE__ */ jsx(StatCard, {
86
+ label: "Projects",
87
+ value: stats.total.toString()
88
+ }),
89
+ /* @__PURE__ */ jsx(StatCard, {
90
+ label: "Active",
91
+ value: stats.activeCount.toString()
92
+ }),
93
+ /* @__PURE__ */ jsx(StatCard, {
94
+ label: "Draft",
95
+ value: stats.draftCount.toString()
96
+ }),
97
+ /* @__PURE__ */ jsx(StatCard, {
98
+ label: "Plan",
99
+ value: subscription.plan,
100
+ hint: subscription.status
101
+ })
102
+ ] }),
103
+ /* @__PURE__ */ jsx("nav", {
104
+ className: "bg-muted flex gap-1 rounded-lg p-1",
105
+ role: "tablist",
106
+ children: tabs.map((tab) => /* @__PURE__ */ jsxs("button", {
107
+ type: "button",
108
+ role: "tab",
109
+ "aria-selected": activeTab === tab.id,
110
+ onClick: () => setActiveTab(tab.id),
111
+ className: `flex flex-1 items-center justify-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-colors ${activeTab === tab.id ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
112
+ children: [/* @__PURE__ */ jsx("span", { children: tab.icon }), tab.label]
113
+ }, tab.id))
114
+ }),
115
+ /* @__PURE__ */ jsxs("div", {
116
+ className: "min-h-[400px]",
117
+ role: "tabpanel",
118
+ children: [
119
+ activeTab === "projects" && /* @__PURE__ */ jsx(ProjectsTab, {
120
+ data,
121
+ onProjectClick: handleProjectClick
122
+ }),
123
+ activeTab === "billing" && /* @__PURE__ */ jsx(BillingTab, { subscription }),
124
+ activeTab === "settings" && /* @__PURE__ */ jsx(SettingsTab, {})
125
+ ]
126
+ }),
127
+ /* @__PURE__ */ jsx(CreateProjectModal, {
128
+ isOpen: isCreateModalOpen,
129
+ onClose: () => setIsCreateModalOpen(false),
130
+ onSubmit: async (input) => {
131
+ await mutations.createProject(input);
132
+ },
133
+ isLoading: mutations.createState.loading
134
+ }),
135
+ /* @__PURE__ */ jsx(ProjectActionsModal, {
136
+ isOpen: isProjectActionsOpen,
137
+ project: selectedProject,
138
+ onClose: () => {
139
+ setIsProjectActionsOpen(false);
140
+ setSelectedProject(null);
141
+ },
142
+ onUpdate: async (input) => {
143
+ await mutations.updateProject(input);
144
+ },
145
+ onArchive: async (projectId) => {
146
+ await mutations.archiveProject(projectId);
147
+ },
148
+ onActivate: async (projectId) => {
149
+ await mutations.activateProject(projectId);
150
+ },
151
+ onDelete: async (projectId) => {
152
+ await mutations.deleteProject(projectId);
153
+ },
154
+ isLoading: mutations.isLoading
155
+ })
156
+ ]
157
+ });
158
+ }
159
+ function ProjectsTab({ data, onProjectClick }) {
160
+ if (!data?.items.length) return /* @__PURE__ */ jsx(EmptyState, {
161
+ title: "No projects yet",
162
+ description: "Create your first project to get started."
163
+ });
164
+ return /* @__PURE__ */ jsx("div", {
165
+ className: "space-y-4",
166
+ children: /* @__PURE__ */ jsx("div", {
167
+ className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3",
168
+ children: data.items.map((project) => /* @__PURE__ */ jsx(EntityCard, {
169
+ cardTitle: project.name,
170
+ cardSubtitle: project.tier,
171
+ meta: /* @__PURE__ */ jsx("p", {
172
+ className: "text-muted-foreground text-sm",
173
+ children: project.description
174
+ }),
175
+ chips: /* @__PURE__ */ jsx(StatusChip, {
176
+ tone: getStatusTone(project.status),
177
+ label: project.status
178
+ }),
179
+ footer: /* @__PURE__ */ jsxs("div", {
180
+ className: "flex w-full items-center justify-between",
181
+ children: [/* @__PURE__ */ jsx("span", {
182
+ className: "text-muted-foreground text-xs",
183
+ children: project.updatedAt.toLocaleDateString()
184
+ }), /* @__PURE__ */ jsx(Button, {
185
+ variant: "ghost",
186
+ size: "sm",
187
+ onPress: () => onProjectClick?.(project),
188
+ children: "Actions"
189
+ })]
190
+ })
191
+ }, project.id))
192
+ })
193
+ });
194
+ }
195
+ function BillingTab({ subscription }) {
196
+ if (!subscription) return null;
197
+ return /* @__PURE__ */ jsxs("div", {
198
+ className: "space-y-6",
199
+ children: [/* @__PURE__ */ jsxs("div", {
200
+ className: "border-border bg-card rounded-xl border p-6",
201
+ children: [/* @__PURE__ */ jsxs("div", {
202
+ className: "flex items-start justify-between",
203
+ children: [/* @__PURE__ */ jsxs("div", { children: [
204
+ /* @__PURE__ */ jsxs("h3", {
205
+ className: "text-lg font-semibold",
206
+ children: [subscription.plan, " Plan"]
207
+ }),
208
+ /* @__PURE__ */ jsxs("p", {
209
+ className: "text-muted-foreground text-sm",
210
+ children: [
211
+ "Current period:",
212
+ " ",
213
+ subscription.currentPeriodStart.toLocaleDateString(),
214
+ " -",
215
+ " ",
216
+ subscription.currentPeriodEnd.toLocaleDateString()
217
+ ]
218
+ }),
219
+ /* @__PURE__ */ jsxs("p", {
220
+ className: "text-muted-foreground text-sm",
221
+ children: ["Billing cycle: ", subscription.billingCycle]
222
+ })
223
+ ] }), /* @__PURE__ */ jsx(StatusChip, {
224
+ tone: "success",
225
+ label: subscription.status
226
+ })]
227
+ }), /* @__PURE__ */ jsxs("div", {
228
+ className: "mt-4 flex gap-3",
229
+ children: [/* @__PURE__ */ jsx(Button, {
230
+ variant: "outline",
231
+ onPress: () => alert("Upgrade clicked!"),
232
+ children: "Upgrade Plan"
233
+ }), /* @__PURE__ */ jsx(Button, {
234
+ variant: "ghost",
235
+ onPress: () => alert("Manage Billing clicked!"),
236
+ children: "Manage Billing"
237
+ })]
238
+ })]
239
+ }), subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsx("div", {
240
+ className: "border-border bg-destructive/10 text-destructive rounded-xl border p-4",
241
+ children: /* @__PURE__ */ jsx("p", {
242
+ className: "text-sm font-medium",
243
+ children: "⚠️ Your subscription will be cancelled at the end of the current period."
244
+ })
245
+ })]
246
+ });
247
+ }
248
+ function SettingsTab() {
249
+ return /* @__PURE__ */ jsx("div", {
250
+ className: "space-y-6",
251
+ children: /* @__PURE__ */ jsxs("div", {
252
+ className: "border-border bg-card rounded-xl border p-6",
253
+ children: [/* @__PURE__ */ jsx("h3", {
254
+ className: "mb-4 text-lg font-semibold",
255
+ children: "Organization Settings"
256
+ }), /* @__PURE__ */ jsxs("div", {
257
+ className: "space-y-4",
258
+ children: [
259
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
260
+ htmlFor: "org-name",
261
+ className: "text-sm font-medium",
262
+ children: "Organization Name"
263
+ }), /* @__PURE__ */ jsx("input", {
264
+ id: "org-name",
265
+ type: "text",
266
+ defaultValue: "Demo Organization",
267
+ className: "border-input bg-background mt-1 block w-full rounded-md border px-3 py-2"
268
+ })] }),
269
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
270
+ htmlFor: "timezone",
271
+ className: "text-sm font-medium",
272
+ children: "Default Timezone"
273
+ }), /* @__PURE__ */ jsxs("select", {
274
+ id: "timezone",
275
+ className: "border-input bg-background mt-1 block w-full rounded-md border px-3 py-2",
276
+ children: [
277
+ /* @__PURE__ */ jsx("option", { children: "UTC" }),
278
+ /* @__PURE__ */ jsx("option", { children: "America/New_York" }),
279
+ /* @__PURE__ */ jsx("option", { children: "Europe/London" }),
280
+ /* @__PURE__ */ jsx("option", { children: "Asia/Tokyo" })
281
+ ]
282
+ })] }),
283
+ /* @__PURE__ */ jsx("div", {
284
+ className: "pt-2",
285
+ children: /* @__PURE__ */ jsx(Button, {
286
+ onPress: () => alert("Settings saved!"),
287
+ children: "Save Settings"
288
+ })
289
+ })
290
+ ]
291
+ })]
292
+ })
293
+ });
294
+ }
295
+
296
+ //#endregion
297
+ export { SaasDashboard };
298
+ //# sourceMappingURL=SaasDashboard.js.map