@house-rules/projects 0.0.0-stage → 0.1.1

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.
@@ -0,0 +1,148 @@
1
+ import { Projects } from "./facade.js";
2
+ import { bindProjects } from "./project/bind-projects.js";
3
+ export declare const ProjectsMount: {
4
+ map: {
5
+ name: string;
6
+ kind: "package";
7
+ role: "capability";
8
+ package: string;
9
+ };
10
+ service: typeof Projects;
11
+ operations: (import("@house-rules/domain").Operation<"Projects.archive", import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
12
+ readonly id: import("effect/Schema").NonEmptyString;
13
+ }>, import("effect/Schema").Struct<{
14
+ readonly slug: import("effect/Schema").NonEmptyString;
15
+ }>]>, import("effect/Schema").Struct<{
16
+ readonly project: import("effect/Schema").Struct<{
17
+ readonly id: import("effect/Schema").NonEmptyString;
18
+ readonly slug: import("effect/Schema").NonEmptyString;
19
+ readonly name: import("effect/Schema").NonEmptyString;
20
+ readonly status: import("effect/Schema").NonEmptyString;
21
+ readonly description: import("effect/Schema").String;
22
+ readonly createdAt: import("effect/Schema").Int;
23
+ readonly updatedAt: import("effect/Schema").Int;
24
+ }>;
25
+ readonly events: import("effect/Schema").$Array<import("effect/Schema").Struct<{
26
+ readonly kind: import("effect/Schema").Literal<"ProjectUpdated">;
27
+ readonly before: import("effect/Schema").Struct<{
28
+ readonly id: import("effect/Schema").NonEmptyString;
29
+ readonly slug: import("effect/Schema").NonEmptyString;
30
+ readonly name: import("effect/Schema").NonEmptyString;
31
+ readonly status: import("effect/Schema").NonEmptyString;
32
+ readonly description: import("effect/Schema").String;
33
+ readonly createdAt: import("effect/Schema").Int;
34
+ readonly updatedAt: import("effect/Schema").Int;
35
+ }>;
36
+ readonly after: import("effect/Schema").Struct<{
37
+ readonly id: import("effect/Schema").NonEmptyString;
38
+ readonly slug: import("effect/Schema").NonEmptyString;
39
+ readonly name: import("effect/Schema").NonEmptyString;
40
+ readonly status: import("effect/Schema").NonEmptyString;
41
+ readonly description: import("effect/Schema").String;
42
+ readonly createdAt: import("effect/Schema").Int;
43
+ readonly updatedAt: import("effect/Schema").Int;
44
+ }>;
45
+ }>>;
46
+ }>, import("effect/Schema").Union<readonly [typeof import("./contract.js").ProjectNotFound, typeof import("./contract.js").ProjectSlugTaken, typeof import("./contract.js").ProjectInputInvalid, typeof import("./contract.js").ProjectAccessDenied, typeof import("./contract.js").ProjectStoreUnavailable, typeof import("./contract.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, false, false, true, false> | import("@house-rules/domain").Operation<"Projects.create", import("effect/Schema").Struct<{
47
+ readonly slug: import("effect/Schema").String;
48
+ readonly name: import("effect/Schema").String;
49
+ readonly status: import("effect/Schema").optionalKey<import("effect/Schema").String>;
50
+ readonly description: import("effect/Schema").optionalKey<import("effect/Schema").String>;
51
+ }>, import("effect/Schema").Struct<{
52
+ readonly project: import("effect/Schema").Struct<{
53
+ readonly id: import("effect/Schema").NonEmptyString;
54
+ readonly slug: import("effect/Schema").NonEmptyString;
55
+ readonly name: import("effect/Schema").NonEmptyString;
56
+ readonly status: import("effect/Schema").NonEmptyString;
57
+ readonly description: import("effect/Schema").String;
58
+ readonly createdAt: import("effect/Schema").Int;
59
+ readonly updatedAt: import("effect/Schema").Int;
60
+ }>;
61
+ readonly events: import("effect/Schema").$Array<import("effect/Schema").Struct<{
62
+ readonly kind: import("effect/Schema").Literal<"ProjectCreated">;
63
+ readonly project: import("effect/Schema").Struct<{
64
+ readonly id: import("effect/Schema").NonEmptyString;
65
+ readonly slug: import("effect/Schema").NonEmptyString;
66
+ readonly name: import("effect/Schema").NonEmptyString;
67
+ readonly status: import("effect/Schema").NonEmptyString;
68
+ readonly description: import("effect/Schema").String;
69
+ readonly createdAt: import("effect/Schema").Int;
70
+ readonly updatedAt: import("effect/Schema").Int;
71
+ }>;
72
+ }>>;
73
+ }>, import("effect/Schema").Union<readonly [typeof import("./contract.js").ProjectNotFound, typeof import("./contract.js").ProjectSlugTaken, typeof import("./contract.js").ProjectInputInvalid, typeof import("./contract.js").ProjectAccessDenied, typeof import("./contract.js").ProjectStoreUnavailable, typeof import("./contract.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, false, false, true, false> | import("@house-rules/domain").Operation<"Projects.list", import("effect/Schema").Struct<{
74
+ readonly status: import("effect/Schema").optionalKey<import("effect/Schema").String>;
75
+ }>, import("effect/Schema").$Array<import("effect/Schema").Struct<{
76
+ readonly id: import("effect/Schema").NonEmptyString;
77
+ readonly slug: import("effect/Schema").NonEmptyString;
78
+ readonly name: import("effect/Schema").NonEmptyString;
79
+ readonly status: import("effect/Schema").NonEmptyString;
80
+ readonly description: import("effect/Schema").String;
81
+ readonly createdAt: import("effect/Schema").Int;
82
+ readonly updatedAt: import("effect/Schema").Int;
83
+ }>>, import("effect/Schema").Union<readonly [typeof import("./contract.js").ProjectNotFound, typeof import("./contract.js").ProjectSlugTaken, typeof import("./contract.js").ProjectInputInvalid, typeof import("./contract.js").ProjectAccessDenied, typeof import("./contract.js").ProjectStoreUnavailable, typeof import("./contract.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, true, false, false, false> | import("@house-rules/domain").Operation<"Projects.show", import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
84
+ readonly id: import("effect/Schema").NonEmptyString;
85
+ }>, import("effect/Schema").Struct<{
86
+ readonly slug: import("effect/Schema").NonEmptyString;
87
+ }>]>, import("effect/Schema").Struct<{
88
+ readonly id: import("effect/Schema").NonEmptyString;
89
+ readonly slug: import("effect/Schema").NonEmptyString;
90
+ readonly name: import("effect/Schema").NonEmptyString;
91
+ readonly status: import("effect/Schema").NonEmptyString;
92
+ readonly description: import("effect/Schema").String;
93
+ readonly createdAt: import("effect/Schema").Int;
94
+ readonly updatedAt: import("effect/Schema").Int;
95
+ }>, import("effect/Schema").Union<readonly [typeof import("./contract.js").ProjectNotFound, typeof import("./contract.js").ProjectSlugTaken, typeof import("./contract.js").ProjectInputInvalid, typeof import("./contract.js").ProjectAccessDenied, typeof import("./contract.js").ProjectStoreUnavailable, typeof import("./contract.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, true, false, false, false> | import("@house-rules/domain").Operation<"Projects.update", import("effect/Schema").Struct<{
96
+ readonly ref: import("effect/Schema").Union<readonly [import("effect/Schema").Struct<{
97
+ readonly id: import("effect/Schema").NonEmptyString;
98
+ }>, import("effect/Schema").Struct<{
99
+ readonly slug: import("effect/Schema").NonEmptyString;
100
+ }>]>;
101
+ readonly patch: import("effect/Schema").Struct<{
102
+ readonly slug: import("effect/Schema").optionalKey<import("effect/Schema").String>;
103
+ readonly name: import("effect/Schema").optionalKey<import("effect/Schema").String>;
104
+ readonly status: import("effect/Schema").optionalKey<import("effect/Schema").String>;
105
+ readonly description: import("effect/Schema").optionalKey<import("effect/Schema").String>;
106
+ }>;
107
+ }>, import("effect/Schema").Struct<{
108
+ readonly project: import("effect/Schema").Struct<{
109
+ readonly id: import("effect/Schema").NonEmptyString;
110
+ readonly slug: import("effect/Schema").NonEmptyString;
111
+ readonly name: import("effect/Schema").NonEmptyString;
112
+ readonly status: import("effect/Schema").NonEmptyString;
113
+ readonly description: import("effect/Schema").String;
114
+ readonly createdAt: import("effect/Schema").Int;
115
+ readonly updatedAt: import("effect/Schema").Int;
116
+ }>;
117
+ readonly events: import("effect/Schema").$Array<import("effect/Schema").Struct<{
118
+ readonly kind: import("effect/Schema").Literal<"ProjectUpdated">;
119
+ readonly before: import("effect/Schema").Struct<{
120
+ readonly id: import("effect/Schema").NonEmptyString;
121
+ readonly slug: import("effect/Schema").NonEmptyString;
122
+ readonly name: import("effect/Schema").NonEmptyString;
123
+ readonly status: import("effect/Schema").NonEmptyString;
124
+ readonly description: import("effect/Schema").String;
125
+ readonly createdAt: import("effect/Schema").Int;
126
+ readonly updatedAt: import("effect/Schema").Int;
127
+ }>;
128
+ readonly after: import("effect/Schema").Struct<{
129
+ readonly id: import("effect/Schema").NonEmptyString;
130
+ readonly slug: import("effect/Schema").NonEmptyString;
131
+ readonly name: import("effect/Schema").NonEmptyString;
132
+ readonly status: import("effect/Schema").NonEmptyString;
133
+ readonly description: import("effect/Schema").String;
134
+ readonly createdAt: import("effect/Schema").Int;
135
+ readonly updatedAt: import("effect/Schema").Int;
136
+ }>;
137
+ }>>;
138
+ }>, import("effect/Schema").Union<readonly [typeof import("./contract.js").ProjectNotFound, typeof import("./contract.js").ProjectSlugTaken, typeof import("./contract.js").ProjectInputInvalid, typeof import("./contract.js").ProjectAccessDenied, typeof import("./contract.js").ProjectStoreUnavailable, typeof import("./contract.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, false, false, true, false>)[];
139
+ bind: typeof bindProjects;
140
+ };
141
+ export { Projects } from "./facade.js";
142
+ export { bindProjects } from "./project/bind-projects.js";
143
+ export { ProjectAccess } from "./project/access.js";
144
+ export { ProjectsOptions } from "./project/options.js";
145
+ export { ProjectStore } from "./storage.js";
146
+ export { memoryProjectStore } from "./adapters/memory/project.js";
147
+ export { postgresProjectStore } from "./adapters/postgres/project.js";
148
+ export { CreateProjectResult, UpdateProjectResult, ProjectEvents, ProjectsOperations, ProjectPermissions, type ProjectPermission, Project, ProjectRef, NewProject, ProjectPatch, ProjectFilter, ProjectFailure, ProjectNotFound, ProjectSlugTaken, ProjectInputInvalid, ProjectAccessDenied, ProjectAccessUnavailable, ProjectStoreUnavailable, } from "./contract.js";
package/dist/index.js ADDED
@@ -0,0 +1,17 @@
1
+ import { Projects } from "./facade.js";
2
+ import { ProjectsOperations } from "./contract.js";
3
+ import { bindProjects } from "./project/bind-projects.js";
4
+ export const ProjectsMount = {
5
+ map: { name: "projects", kind: "package", role: "capability", package: "@house-rules/projects" },
6
+ service: Projects,
7
+ operations: Object.values(ProjectsOperations),
8
+ bind: bindProjects,
9
+ };
10
+ export { Projects } from "./facade.js";
11
+ export { bindProjects } from "./project/bind-projects.js";
12
+ export { ProjectAccess } from "./project/access.js";
13
+ export { ProjectsOptions } from "./project/options.js";
14
+ export { ProjectStore } from "./storage.js";
15
+ export { memoryProjectStore } from "./adapters/memory/project.js";
16
+ export { postgresProjectStore } from "./adapters/postgres/project.js";
17
+ export { CreateProjectResult, UpdateProjectResult, ProjectEvents, ProjectsOperations, ProjectPermissions, Project, ProjectRef, NewProject, ProjectPatch, ProjectFilter, ProjectFailure, ProjectNotFound, ProjectSlugTaken, ProjectInputInvalid, ProjectAccessDenied, ProjectAccessUnavailable, ProjectStoreUnavailable, } from "./contract.js";
@@ -0,0 +1,10 @@
1
+ import type { Actor } from "@house-rules/domain";
2
+ import { Context, type Effect } from "effect";
3
+ import type { ProjectAccessUnavailable } from "./project.js";
4
+ declare const ProjectAccess_base: Context.ServiceClass<ProjectAccess, "@house-rules/projects/ProjectAccess", {
5
+ readonly access: (actor: Actor, projectId: string | null) => Effect.Effect<"write" | "read" | "none", ProjectAccessUnavailable>;
6
+ readonly visibleProjects: (actor: Actor) => Effect.Effect<ReadonlyArray<string>, ProjectAccessUnavailable>;
7
+ }>;
8
+ export declare class ProjectAccess extends ProjectAccess_base {
9
+ }
10
+ export {};
@@ -0,0 +1,3 @@
1
+ import { Context } from "effect";
2
+ export class ProjectAccess extends Context.Service()("@house-rules/projects/ProjectAccess") {
3
+ }
@@ -0,0 +1,3 @@
1
+ import { type Binding } from "@house-rules/application";
2
+ import type { makeProjects } from "./projects.js";
3
+ export declare const bindProjects: (service: ReturnType<typeof makeProjects>) => readonly Binding[];
@@ -0,0 +1,21 @@
1
+ import { bindOperation } from "@house-rules/application";
2
+ import { Effect } from "effect";
3
+ import { ProjectsOperations } from "./operations.js";
4
+ import { ProjectAccessDenied } from "./project.js";
5
+ export const bindProjects = (service) => [
6
+ bindOperation(ProjectsOperations.create, (input, { caller }) => caller.kind === "person"
7
+ ? service.create(caller.actor, input)
8
+ : Effect.fail(new ProjectAccessDenied())),
9
+ bindOperation(ProjectsOperations.update, ({ ref, patch }, { caller }) => caller.kind === "person"
10
+ ? service.update(caller.actor, ref, patch)
11
+ : Effect.fail(new ProjectAccessDenied())),
12
+ bindOperation(ProjectsOperations.show, (ref, { caller }) => caller.kind === "person"
13
+ ? service.show(caller.actor, ref)
14
+ : Effect.fail(new ProjectAccessDenied())),
15
+ bindOperation(ProjectsOperations.list, (filter, { caller }) => caller.kind === "person"
16
+ ? service.list(caller.actor, filter)
17
+ : Effect.fail(new ProjectAccessDenied())),
18
+ bindOperation(ProjectsOperations.archive, (ref, { caller }) => caller.kind === "person"
19
+ ? service.archive(caller.actor, ref)
20
+ : Effect.fail(new ProjectAccessDenied())),
21
+ ];
@@ -0,0 +1,93 @@
1
+ import { Schema } from "effect";
2
+ export declare const ProjectEvents: {
3
+ readonly ProjectCreated: Schema.Struct<{
4
+ readonly kind: Schema.Literal<"ProjectCreated">;
5
+ readonly project: Schema.Struct<{
6
+ readonly id: Schema.NonEmptyString;
7
+ readonly slug: Schema.NonEmptyString;
8
+ readonly name: Schema.NonEmptyString;
9
+ readonly status: Schema.NonEmptyString;
10
+ readonly description: Schema.String;
11
+ readonly createdAt: Schema.Int;
12
+ readonly updatedAt: Schema.Int;
13
+ }>;
14
+ }>;
15
+ readonly ProjectUpdated: Schema.Struct<{
16
+ readonly kind: Schema.Literal<"ProjectUpdated">;
17
+ readonly before: Schema.Struct<{
18
+ readonly id: Schema.NonEmptyString;
19
+ readonly slug: Schema.NonEmptyString;
20
+ readonly name: Schema.NonEmptyString;
21
+ readonly status: Schema.NonEmptyString;
22
+ readonly description: Schema.String;
23
+ readonly createdAt: Schema.Int;
24
+ readonly updatedAt: Schema.Int;
25
+ }>;
26
+ readonly after: Schema.Struct<{
27
+ readonly id: Schema.NonEmptyString;
28
+ readonly slug: Schema.NonEmptyString;
29
+ readonly name: Schema.NonEmptyString;
30
+ readonly status: Schema.NonEmptyString;
31
+ readonly description: Schema.String;
32
+ readonly createdAt: Schema.Int;
33
+ readonly updatedAt: Schema.Int;
34
+ }>;
35
+ }>;
36
+ };
37
+ export declare const CreateProjectResult: Schema.Struct<{
38
+ readonly project: Schema.Struct<{
39
+ readonly id: Schema.NonEmptyString;
40
+ readonly slug: Schema.NonEmptyString;
41
+ readonly name: Schema.NonEmptyString;
42
+ readonly status: Schema.NonEmptyString;
43
+ readonly description: Schema.String;
44
+ readonly createdAt: Schema.Int;
45
+ readonly updatedAt: Schema.Int;
46
+ }>;
47
+ readonly events: Schema.$Array<Schema.Struct<{
48
+ readonly kind: Schema.Literal<"ProjectCreated">;
49
+ readonly project: Schema.Struct<{
50
+ readonly id: Schema.NonEmptyString;
51
+ readonly slug: Schema.NonEmptyString;
52
+ readonly name: Schema.NonEmptyString;
53
+ readonly status: Schema.NonEmptyString;
54
+ readonly description: Schema.String;
55
+ readonly createdAt: Schema.Int;
56
+ readonly updatedAt: Schema.Int;
57
+ }>;
58
+ }>>;
59
+ }>;
60
+ export type CreateProjectResult = typeof CreateProjectResult.Type;
61
+ export declare const UpdateProjectResult: Schema.Struct<{
62
+ readonly project: Schema.Struct<{
63
+ readonly id: Schema.NonEmptyString;
64
+ readonly slug: Schema.NonEmptyString;
65
+ readonly name: Schema.NonEmptyString;
66
+ readonly status: Schema.NonEmptyString;
67
+ readonly description: Schema.String;
68
+ readonly createdAt: Schema.Int;
69
+ readonly updatedAt: Schema.Int;
70
+ }>;
71
+ readonly events: Schema.$Array<Schema.Struct<{
72
+ readonly kind: Schema.Literal<"ProjectUpdated">;
73
+ readonly before: Schema.Struct<{
74
+ readonly id: Schema.NonEmptyString;
75
+ readonly slug: Schema.NonEmptyString;
76
+ readonly name: Schema.NonEmptyString;
77
+ readonly status: Schema.NonEmptyString;
78
+ readonly description: Schema.String;
79
+ readonly createdAt: Schema.Int;
80
+ readonly updatedAt: Schema.Int;
81
+ }>;
82
+ readonly after: Schema.Struct<{
83
+ readonly id: Schema.NonEmptyString;
84
+ readonly slug: Schema.NonEmptyString;
85
+ readonly name: Schema.NonEmptyString;
86
+ readonly status: Schema.NonEmptyString;
87
+ readonly description: Schema.String;
88
+ readonly createdAt: Schema.Int;
89
+ readonly updatedAt: Schema.Int;
90
+ }>;
91
+ }>>;
92
+ }>;
93
+ export type UpdateProjectResult = typeof UpdateProjectResult.Type;
@@ -0,0 +1,17 @@
1
+ import { Schema } from "effect";
2
+ import { Project } from "./project.js";
3
+ const ProjectCreated = Schema.Struct({ kind: Schema.Literal("ProjectCreated"), project: Project });
4
+ const ProjectUpdated = Schema.Struct({
5
+ kind: Schema.Literal("ProjectUpdated"),
6
+ before: Project,
7
+ after: Project,
8
+ });
9
+ export const ProjectEvents = { ProjectCreated, ProjectUpdated };
10
+ export const CreateProjectResult = Schema.Struct({
11
+ project: Project,
12
+ events: Schema.Array(ProjectCreated),
13
+ });
14
+ export const UpdateProjectResult = Schema.Struct({
15
+ project: Project,
16
+ events: Schema.Array(ProjectUpdated),
17
+ });
@@ -0,0 +1,135 @@
1
+ import { Schema } from "effect";
2
+ export declare const ProjectsOperations: {
3
+ readonly create: import("@house-rules/domain/contract").Operation<"Projects.create", Schema.Struct<{
4
+ readonly slug: Schema.String;
5
+ readonly name: Schema.String;
6
+ readonly status: Schema.optionalKey<Schema.String>;
7
+ readonly description: Schema.optionalKey<Schema.String>;
8
+ }>, Schema.Struct<{
9
+ readonly project: Schema.Struct<{
10
+ readonly id: Schema.NonEmptyString;
11
+ readonly slug: Schema.NonEmptyString;
12
+ readonly name: Schema.NonEmptyString;
13
+ readonly status: Schema.NonEmptyString;
14
+ readonly description: Schema.String;
15
+ readonly createdAt: Schema.Int;
16
+ readonly updatedAt: Schema.Int;
17
+ }>;
18
+ readonly events: Schema.$Array<Schema.Struct<{
19
+ readonly kind: Schema.Literal<"ProjectCreated">;
20
+ readonly project: Schema.Struct<{
21
+ readonly id: Schema.NonEmptyString;
22
+ readonly slug: Schema.NonEmptyString;
23
+ readonly name: Schema.NonEmptyString;
24
+ readonly status: Schema.NonEmptyString;
25
+ readonly description: Schema.String;
26
+ readonly createdAt: Schema.Int;
27
+ readonly updatedAt: Schema.Int;
28
+ }>;
29
+ }>>;
30
+ }>, Schema.Union<readonly [typeof import("./project.js").ProjectNotFound, typeof import("./project.js").ProjectSlugTaken, typeof import("./project.js").ProjectInputInvalid, typeof import("./project.js").ProjectAccessDenied, typeof import("./project.js").ProjectStoreUnavailable, typeof import("./project.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, false, false, true, false>;
31
+ readonly update: import("@house-rules/domain/contract").Operation<"Projects.update", Schema.Struct<{
32
+ readonly ref: Schema.Union<readonly [Schema.Struct<{
33
+ readonly id: Schema.NonEmptyString;
34
+ }>, Schema.Struct<{
35
+ readonly slug: Schema.NonEmptyString;
36
+ }>]>;
37
+ readonly patch: Schema.Struct<{
38
+ readonly slug: Schema.optionalKey<Schema.String>;
39
+ readonly name: Schema.optionalKey<Schema.String>;
40
+ readonly status: Schema.optionalKey<Schema.String>;
41
+ readonly description: Schema.optionalKey<Schema.String>;
42
+ }>;
43
+ }>, Schema.Struct<{
44
+ readonly project: Schema.Struct<{
45
+ readonly id: Schema.NonEmptyString;
46
+ readonly slug: Schema.NonEmptyString;
47
+ readonly name: Schema.NonEmptyString;
48
+ readonly status: Schema.NonEmptyString;
49
+ readonly description: Schema.String;
50
+ readonly createdAt: Schema.Int;
51
+ readonly updatedAt: Schema.Int;
52
+ }>;
53
+ readonly events: Schema.$Array<Schema.Struct<{
54
+ readonly kind: Schema.Literal<"ProjectUpdated">;
55
+ readonly before: Schema.Struct<{
56
+ readonly id: Schema.NonEmptyString;
57
+ readonly slug: Schema.NonEmptyString;
58
+ readonly name: Schema.NonEmptyString;
59
+ readonly status: Schema.NonEmptyString;
60
+ readonly description: Schema.String;
61
+ readonly createdAt: Schema.Int;
62
+ readonly updatedAt: Schema.Int;
63
+ }>;
64
+ readonly after: Schema.Struct<{
65
+ readonly id: Schema.NonEmptyString;
66
+ readonly slug: Schema.NonEmptyString;
67
+ readonly name: Schema.NonEmptyString;
68
+ readonly status: Schema.NonEmptyString;
69
+ readonly description: Schema.String;
70
+ readonly createdAt: Schema.Int;
71
+ readonly updatedAt: Schema.Int;
72
+ }>;
73
+ }>>;
74
+ }>, Schema.Union<readonly [typeof import("./project.js").ProjectNotFound, typeof import("./project.js").ProjectSlugTaken, typeof import("./project.js").ProjectInputInvalid, typeof import("./project.js").ProjectAccessDenied, typeof import("./project.js").ProjectStoreUnavailable, typeof import("./project.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, false, false, true, false>;
75
+ readonly show: import("@house-rules/domain/contract").Operation<"Projects.show", Schema.Union<readonly [Schema.Struct<{
76
+ readonly id: Schema.NonEmptyString;
77
+ }>, Schema.Struct<{
78
+ readonly slug: Schema.NonEmptyString;
79
+ }>]>, Schema.Struct<{
80
+ readonly id: Schema.NonEmptyString;
81
+ readonly slug: Schema.NonEmptyString;
82
+ readonly name: Schema.NonEmptyString;
83
+ readonly status: Schema.NonEmptyString;
84
+ readonly description: Schema.String;
85
+ readonly createdAt: Schema.Int;
86
+ readonly updatedAt: Schema.Int;
87
+ }>, Schema.Union<readonly [typeof import("./project.js").ProjectNotFound, typeof import("./project.js").ProjectSlugTaken, typeof import("./project.js").ProjectInputInvalid, typeof import("./project.js").ProjectAccessDenied, typeof import("./project.js").ProjectStoreUnavailable, typeof import("./project.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, true, false, false, false>;
88
+ readonly list: import("@house-rules/domain/contract").Operation<"Projects.list", Schema.Struct<{
89
+ readonly status: Schema.optionalKey<Schema.String>;
90
+ }>, Schema.$Array<Schema.Struct<{
91
+ readonly id: Schema.NonEmptyString;
92
+ readonly slug: Schema.NonEmptyString;
93
+ readonly name: Schema.NonEmptyString;
94
+ readonly status: Schema.NonEmptyString;
95
+ readonly description: Schema.String;
96
+ readonly createdAt: Schema.Int;
97
+ readonly updatedAt: Schema.Int;
98
+ }>>, Schema.Union<readonly [typeof import("./project.js").ProjectNotFound, typeof import("./project.js").ProjectSlugTaken, typeof import("./project.js").ProjectInputInvalid, typeof import("./project.js").ProjectAccessDenied, typeof import("./project.js").ProjectStoreUnavailable, typeof import("./project.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, true, false, false, false>;
99
+ readonly archive: import("@house-rules/domain/contract").Operation<"Projects.archive", Schema.Union<readonly [Schema.Struct<{
100
+ readonly id: Schema.NonEmptyString;
101
+ }>, Schema.Struct<{
102
+ readonly slug: Schema.NonEmptyString;
103
+ }>]>, Schema.Struct<{
104
+ readonly project: Schema.Struct<{
105
+ readonly id: Schema.NonEmptyString;
106
+ readonly slug: Schema.NonEmptyString;
107
+ readonly name: Schema.NonEmptyString;
108
+ readonly status: Schema.NonEmptyString;
109
+ readonly description: Schema.String;
110
+ readonly createdAt: Schema.Int;
111
+ readonly updatedAt: Schema.Int;
112
+ }>;
113
+ readonly events: Schema.$Array<Schema.Struct<{
114
+ readonly kind: Schema.Literal<"ProjectUpdated">;
115
+ readonly before: Schema.Struct<{
116
+ readonly id: Schema.NonEmptyString;
117
+ readonly slug: Schema.NonEmptyString;
118
+ readonly name: Schema.NonEmptyString;
119
+ readonly status: Schema.NonEmptyString;
120
+ readonly description: Schema.String;
121
+ readonly createdAt: Schema.Int;
122
+ readonly updatedAt: Schema.Int;
123
+ }>;
124
+ readonly after: Schema.Struct<{
125
+ readonly id: Schema.NonEmptyString;
126
+ readonly slug: Schema.NonEmptyString;
127
+ readonly name: Schema.NonEmptyString;
128
+ readonly status: Schema.NonEmptyString;
129
+ readonly description: Schema.String;
130
+ readonly createdAt: Schema.Int;
131
+ readonly updatedAt: Schema.Int;
132
+ }>;
133
+ }>>;
134
+ }>, Schema.Union<readonly [typeof import("./project.js").ProjectNotFound, typeof import("./project.js").ProjectSlugTaken, typeof import("./project.js").ProjectInputInvalid, typeof import("./project.js").ProjectAccessDenied, typeof import("./project.js").ProjectStoreUnavailable, typeof import("./project.js").ProjectAccessUnavailable]>, NoInfer<readonly []>, false, false, true, false>;
135
+ };
@@ -0,0 +1,51 @@
1
+ import { defineOperation } from "@house-rules/domain/contract";
2
+ import { Schema } from "effect";
3
+ import { CreateProjectResult, UpdateProjectResult } from "./events.js";
4
+ import { NewProject, Project, ProjectFailure, ProjectFilter, ProjectPatch, ProjectRef, } from "./project.js";
5
+ import { ProjectPermissions } from "./permissions.js";
6
+ const create = defineOperation("Projects.create", {
7
+ description: "Create a project with a unique slug.",
8
+ input: NewProject,
9
+ output: CreateProjectResult,
10
+ failure: ProjectFailure,
11
+ permission: ProjectPermissions.write,
12
+ edges: [],
13
+ transactional: true,
14
+ });
15
+ const update = defineOperation("Projects.update", {
16
+ description: "Change a project's fields, including its slug.",
17
+ input: Schema.Struct({ ref: ProjectRef, patch: ProjectPatch }),
18
+ output: UpdateProjectResult,
19
+ failure: ProjectFailure,
20
+ permission: ProjectPermissions.write,
21
+ edges: [],
22
+ transactional: true,
23
+ });
24
+ const show = defineOperation("Projects.show", {
25
+ description: "Read a project by id or slug.",
26
+ input: ProjectRef,
27
+ output: Project,
28
+ failure: ProjectFailure,
29
+ permission: ProjectPermissions.read,
30
+ edges: [],
31
+ readOnly: true,
32
+ });
33
+ const list = defineOperation("Projects.list", {
34
+ description: "List projects by case-insensitive name then slug, optionally filtering status.",
35
+ input: ProjectFilter,
36
+ output: Schema.Array(Project),
37
+ failure: ProjectFailure,
38
+ permission: ProjectPermissions.read,
39
+ edges: [],
40
+ readOnly: true,
41
+ });
42
+ const archive = defineOperation("Projects.archive", {
43
+ description: "Set a project to the configured archived status.",
44
+ input: ProjectRef,
45
+ output: UpdateProjectResult,
46
+ failure: ProjectFailure,
47
+ permission: ProjectPermissions.write,
48
+ edges: [],
49
+ transactional: true,
50
+ });
51
+ export const ProjectsOperations = { create, update, show, list, archive };
@@ -0,0 +1,26 @@
1
+ import { Schema } from "effect";
2
+ export declare const ProjectsOptions: Schema.Struct<{
3
+ readonly statuses: Schema.$Array<Schema.NonEmptyString>;
4
+ readonly defaultStatus: Schema.NonEmptyString;
5
+ readonly archivedStatus: Schema.NonEmptyString;
6
+ readonly slug: Schema.Struct<{
7
+ readonly pattern: Schema.String;
8
+ readonly maxLength: Schema.Int;
9
+ readonly lowercase: Schema.Boolean;
10
+ readonly trim: Schema.Boolean;
11
+ }>;
12
+ }>;
13
+ export type ProjectsOptions = typeof ProjectsOptions.Type;
14
+ export declare const projectsPresets: {
15
+ readonly default: {
16
+ readonly statuses: readonly ["active", "archived"];
17
+ readonly defaultStatus: "active";
18
+ readonly archivedStatus: "archived";
19
+ readonly slug: {
20
+ readonly pattern: "^[a-z0-9][a-z0-9-]*$";
21
+ readonly maxLength: 64;
22
+ readonly lowercase: true;
23
+ readonly trim: true;
24
+ };
25
+ };
26
+ };
@@ -0,0 +1,20 @@
1
+ import { Schema } from "effect";
2
+ export const ProjectsOptions = Schema.Struct({
3
+ statuses: Schema.Array(Schema.NonEmptyString).check(Schema.isMinLength(1)),
4
+ defaultStatus: Schema.NonEmptyString,
5
+ archivedStatus: Schema.NonEmptyString,
6
+ slug: Schema.Struct({
7
+ pattern: Schema.String,
8
+ maxLength: Schema.Int.check(Schema.isGreaterThan(0)),
9
+ lowercase: Schema.Boolean,
10
+ trim: Schema.Boolean,
11
+ }),
12
+ });
13
+ export const projectsPresets = {
14
+ default: {
15
+ statuses: ["active", "archived"],
16
+ defaultStatus: "active",
17
+ archivedStatus: "archived",
18
+ slug: { pattern: "^[a-z0-9][a-z0-9-]*$", maxLength: 64, lowercase: true, trim: true },
19
+ },
20
+ };
@@ -0,0 +1,2 @@
1
+ import type { Project } from "./project.js";
2
+ export declare const projectOrder: (a: Project, b: Project) => number;
@@ -0,0 +1,2 @@
1
+ const compare = (a, b) => (a < b ? -1 : a === b ? 0 : 1);
2
+ export const projectOrder = (a, b) => compare(a.name.toLowerCase(), b.name.toLowerCase()) || compare(a.slug, b.slug);
@@ -0,0 +1,5 @@
1
+ export declare const ProjectPermissions: {
2
+ readonly read: "projects:read";
3
+ readonly write: "projects:write";
4
+ };
5
+ export type ProjectPermission = (typeof ProjectPermissions)[keyof typeof ProjectPermissions];
@@ -0,0 +1 @@
1
+ export const ProjectPermissions = { read: "projects:read", write: "projects:write" };