@newschools/sdk 0.1.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.
@@ -0,0 +1,164 @@
1
+ /**
2
+ * New Schools Path Resolver
3
+ *
4
+ * Responsible for resolving API endpoint paths for different resource types
5
+ * Follows DDD single responsibility principle - only handles path resolution
6
+ *
7
+ * Adding new resources:
8
+ * 1. Add resource type to ResourceType union
9
+ * 2. Add resolver function to RESOLVERS registry
10
+ * 3. Type safety ensures correct parameters
11
+ */
12
+
13
+ /**
14
+ * Resource type discriminator
15
+ * Determines whether we're fetching a list or single entity
16
+ */
17
+ export type ResourceAction = "list" | "get";
18
+
19
+ /**
20
+ * Parameters for different resource types
21
+ */
22
+ export interface JourneyParams {
23
+ id?: string;
24
+ }
25
+
26
+ export interface WaypointParams {
27
+ journeyId: string;
28
+ waypointId?: string;
29
+ }
30
+
31
+ export interface ActivityParams {
32
+ journeyId: string;
33
+ waypointId: string;
34
+ activityId?: string;
35
+ }
36
+
37
+ /**
38
+ * Union of all possible parameter types
39
+ */
40
+ export type ResourceParams = JourneyParams | WaypointParams | ActivityParams;
41
+
42
+ /**
43
+ * Path resolver function signature
44
+ * Takes action and params, returns endpoint path
45
+ */
46
+ type PathResolverFn<T extends ResourceParams> = (
47
+ action: ResourceAction,
48
+ params?: T,
49
+ ) => string;
50
+
51
+ /**
52
+ * Registry of path resolvers for each resource type
53
+ * Each resolver is responsible for building paths for that resource
54
+ */
55
+ const RESOLVERS = {
56
+ /**
57
+ * Journey path resolver
58
+ * - List: /journeys
59
+ * - Get: /journeys/{id}
60
+ */
61
+ journey: ((action: ResourceAction, params?: JourneyParams): string => {
62
+ if (action === "list") {
63
+ return "/journeys";
64
+ }
65
+
66
+ if (!params?.id) {
67
+ throw new Error("[PathResolver] Journey ID is required for get action");
68
+ }
69
+
70
+ return `/journeys/${params.id}`;
71
+ }) as PathResolverFn<JourneyParams>,
72
+
73
+ /**
74
+ * Waypoint path resolver
75
+ * - List: /journeys/{journeyId}/waypoints
76
+ * - Get: /journeys/{journeyId}/waypoints/{waypointId}
77
+ */
78
+ waypoint: ((action: ResourceAction, params?: WaypointParams): string => {
79
+ if (!params?.journeyId) {
80
+ throw new Error("[PathResolver] journeyId is required for waypoints");
81
+ }
82
+
83
+ if (action === "list") {
84
+ return `/journeys/${params.journeyId}/waypoints`;
85
+ }
86
+
87
+ if (!params.waypointId) {
88
+ throw new Error("[PathResolver] waypointId is required for get action");
89
+ }
90
+
91
+ return `/journeys/${params.journeyId}/waypoints/${params.waypointId}`;
92
+ }) as PathResolverFn<WaypointParams>,
93
+
94
+ /**
95
+ * Activity path resolver
96
+ * - List: /journeys/{journeyId}/waypoints/{waypointId}/activities
97
+ * - Get: /journeys/{journeyId}/waypoints/{waypointId}/activities/{activityId}
98
+ */
99
+ activity: ((action: ResourceAction, params?: ActivityParams): string => {
100
+ if (!params?.journeyId || !params?.waypointId) {
101
+ throw new Error(
102
+ "[PathResolver] journeyId and waypointId are required for activities",
103
+ );
104
+ }
105
+
106
+ if (action === "list") {
107
+ return `/journeys/${params.journeyId}/waypoints/${params.waypointId}/activities`;
108
+ }
109
+
110
+ if (!params.activityId) {
111
+ throw new Error("[PathResolver] activityId is required for get action");
112
+ }
113
+
114
+ return `/journeys/${params.journeyId}/waypoints/${params.waypointId}/activities/${params.activityId}`;
115
+ }) as PathResolverFn<ActivityParams>,
116
+ };
117
+
118
+ /**
119
+ * Resource types that have resolvers
120
+ */
121
+ export type ResourceType = keyof typeof RESOLVERS;
122
+
123
+ /**
124
+ * New Schools Path Resolver Service
125
+ * Resolves API endpoint paths based on resource type and parameters
126
+ */
127
+ export class NewSchoolsPathResolver {
128
+ /**
129
+ * Resolve endpoint path for a resource
130
+ *
131
+ * @param resourceType - Type of resource (journey, waypoint, activity)
132
+ * @param action - Action to perform (list or get)
133
+ * @param params - Resource-specific parameters
134
+ * @returns API endpoint path (e.g., "/journeys/123/waypoints")
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * // List all journeys
139
+ * NewSchoolsPathResolver.resolve('journey', 'list')
140
+ * // => '/journeys'
141
+ *
142
+ * // Get single journey
143
+ * NewSchoolsPathResolver.resolve('journey', 'get', { id: '123' })
144
+ * // => '/journeys/123'
145
+ *
146
+ * // List waypoints for journey
147
+ * NewSchoolsPathResolver.resolve('waypoint', 'list', { journeyId: '123' })
148
+ * // => '/journeys/123/waypoints'
149
+ * ```
150
+ */
151
+ static resolve(
152
+ resourceType: ResourceType,
153
+ action: ResourceAction,
154
+ params?: ResourceParams,
155
+ ): string {
156
+ const resolver = RESOLVERS[resourceType];
157
+
158
+ if (!resolver) {
159
+ throw new Error(`[PathResolver] Unknown resource type: ${resourceType}`);
160
+ }
161
+
162
+ return resolver(action, params as any);
163
+ }
164
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * API Response Types
3
+ * Standard API response shapes for New Schools v1 API
4
+ */
5
+
6
+ /**
7
+ * Standard success response shape
8
+ * All successful API responses follow this structure
9
+ */
10
+ export interface SuccessResponse<T = unknown> {
11
+ success: true;
12
+ data: T;
13
+ message: string;
14
+ meta?: {
15
+ requestId?: string;
16
+ timestamp?: string;
17
+ took?: number; // Response time in ms
18
+ };
19
+ }
20
+
21
+ /**
22
+ * Standard error response shape
23
+ * All error API responses follow this structure
24
+ */
25
+ export interface ErrorResponse {
26
+ success: false;
27
+ error: {
28
+ code: string; // Machine-readable error code (e.g., "JOURNEY_NOT_FOUND")
29
+ message: string; // Human-readable error message
30
+ statusCode: number; // HTTP status code
31
+ details?: unknown; // Optional context (validation errors, field-level details, etc.)
32
+ stack?: string; // Stack trace (only included in development mode)
33
+ };
34
+ meta?: {
35
+ requestId?: string;
36
+ timestamp?: string;
37
+ path?: string;
38
+ };
39
+ }
40
+
41
+ /**
42
+ * Union type for all API responses
43
+ */
44
+ export type ApiResponse<T = unknown> = SuccessResponse<T> | ErrorResponse;
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Entity Types for New Schools v1 API
3
+ * Public-facing types that match API responses
4
+ *
5
+ * Note: These are simplified versions containing only public fields.
6
+ * Internal implementation details (moderation, Firebase paths, etc.) are omitted.
7
+ */
8
+
9
+ /**
10
+ * Journey Theme Type
11
+ * Available theme options that determine UI terminology
12
+ * - adventure: K-12, gamified learners (Journey → Waypoint → Quest)
13
+ * - academic: Traditional education (Course → Module → Lesson)
14
+ * - professional: Corporate training (Program → Milestone → Activity)
15
+ */
16
+ export type JourneyTheme = "adventure" | "academic" | "professional";
17
+
18
+ /**
19
+ * Journey Status Type
20
+ * - draft: Being created, not visible to students
21
+ * - published: Active and visible to students
22
+ */
23
+ export type JourneyStatus = "draft" | "published";
24
+
25
+ /**
26
+ * Journey Entity
27
+ * Top-level learning container (Course/Program)
28
+ * Contains waypoints with activities
29
+ */
30
+ export interface Journey {
31
+ /** Unique identifier */
32
+ id: string;
33
+
34
+ /** URL-friendly identifier */
35
+ slug: string;
36
+
37
+ /** Journey title */
38
+ title: string;
39
+
40
+ /** Journey description */
41
+ description?: string;
42
+
43
+ /** AI-generated summary */
44
+ summary?: string;
45
+
46
+ /** Organisation ID this journey belongs to */
47
+ organisationId: string;
48
+
49
+ /**
50
+ * Journey visibility
51
+ * - private: Only visible to enrolled learners
52
+ * - public: Listed in marketplace, anyone can enroll
53
+ */
54
+ visibility: "private" | "public";
55
+
56
+ /** Theme determines UI terminology */
57
+ theme: JourneyTheme;
58
+
59
+ /** Journey status */
60
+ status: JourneyStatus;
61
+
62
+ /** Number of waypoints in this journey */
63
+ waypointCount: number;
64
+
65
+ /** Total number of activities across all waypoints */
66
+ activityCount: number;
67
+
68
+ /** Cover image public URL */
69
+ coverImageUrl?: string;
70
+
71
+ /** Creation timestamp (ISO 8601 string) */
72
+ createdAt: string;
73
+
74
+ /** Last update timestamp (ISO 8601 string) */
75
+ updatedAt: string;
76
+ }
77
+
78
+ /**
79
+ * Waypoint Type
80
+ * Four distinct types of waypoints in a journey
81
+ */
82
+ export type WaypointType =
83
+ | "standard"
84
+ | "startingPoint"
85
+ | "checkpoint"
86
+ | "exitReflection";
87
+
88
+ /**
89
+ * Layout Mode Type
90
+ * Determines how activities are organized within standard waypoints
91
+ */
92
+ export type LayoutMode = "linear" | "grid";
93
+
94
+ /**
95
+ * Waypoint Status Type
96
+ */
97
+ export type WaypointStatus = "draft" | "published";
98
+
99
+ /**
100
+ * Question for Profile Enrichment Waypoints
101
+ * AI asks these conversationally in chat interface
102
+ */
103
+ export interface Question {
104
+ /** Unique question ID */
105
+ id: string;
106
+
107
+ /** Question text that AI will ask conversationally */
108
+ prompt: string;
109
+
110
+ /** Storage key in student journey profile */
111
+ profileKey: string;
112
+
113
+ /** Optional context for AI on how to approach this question */
114
+ guidance?: string;
115
+ }
116
+
117
+ /**
118
+ * Standard Waypoint
119
+ * Learning container with activities
120
+ */
121
+ export interface StandardWaypoint {
122
+ id: string;
123
+ journeyId: string;
124
+ slug: string;
125
+ title: string;
126
+ description?: string;
127
+ order: number;
128
+ waypointType: "standard";
129
+ status: WaypointStatus;
130
+ layoutMode: LayoutMode;
131
+ activityCount: number;
132
+ createdAt: string;
133
+ updatedAt: string;
134
+ }
135
+
136
+ /**
137
+ * Profile Enrichment Waypoint
138
+ * Gathers information from learners at journey start, checkpoints, or end
139
+ */
140
+ export interface ProfileEnrichmentWaypoint {
141
+ id: string;
142
+ journeyId: string;
143
+ slug: string;
144
+ title: string;
145
+ description?: string;
146
+ order: number;
147
+ waypointType: "startingPoint" | "checkpoint" | "exitReflection";
148
+ status: WaypointStatus;
149
+ questions: Question[];
150
+ createdAt: string;
151
+ updatedAt: string;
152
+ }
153
+
154
+ /**
155
+ * Union type for all waypoint types
156
+ */
157
+ export type Waypoint = StandardWaypoint | ProfileEnrichmentWaypoint;
158
+
159
+ /**
160
+ * Activity Status Type
161
+ */
162
+ export type ActivityStatus = "draft" | "published";
163
+
164
+ /**
165
+ * Grid Position for hub & rings layout
166
+ * Position in 5x5 grid (0-indexed)
167
+ */
168
+ export interface GridPosition {
169
+ row: number;
170
+ col: number;
171
+ }
172
+
173
+ /**
174
+ * Activity Entity
175
+ * A specific learning session within a standard waypoint
176
+ */
177
+ export interface Activity {
178
+ id: string;
179
+ waypointId: string;
180
+ journeyId: string;
181
+ slug: string;
182
+ title: string;
183
+ description?: string;
184
+
185
+ /** Position in sequential order (linear mode only) */
186
+ order?: number;
187
+
188
+ /** Whether this activity must be completed before next (linear mode only) */
189
+ isLinked?: boolean;
190
+
191
+ /** Position in 5x5 hub & rings grid (grid mode only) */
192
+ gridPosition?: GridPosition;
193
+
194
+ status: ActivityStatus;
195
+ createdAt: string;
196
+ updatedAt: string;
197
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Type Exports for New Schools SDK
3
+ * Re-exports all public types
4
+ */
5
+
6
+ // API Response Types
7
+ export type { SuccessResponse, ErrorResponse, ApiResponse } from "./api";
8
+
9
+ // Entity Types
10
+ export type {
11
+ Journey,
12
+ JourneyTheme,
13
+ JourneyStatus,
14
+ Waypoint,
15
+ StandardWaypoint,
16
+ ProfileEnrichmentWaypoint,
17
+ WaypointType,
18
+ WaypointStatus,
19
+ LayoutMode,
20
+ Question,
21
+ Activity,
22
+ ActivityStatus,
23
+ GridPosition,
24
+ } from "./entities";
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@newschools/sdk",
3
+ "version": "0.1.0",
4
+ "description": "New Schools SDK - Multi-framework components and modules for integrating New Schools learning content",
5
+ "type": "module",
6
+ "main": "./nuxt/src/module.ts",
7
+ "types": "./nuxt/src/module.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./nuxt/src/module.ts",
11
+ "types": "./nuxt/src/module.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "nuxt/src",
16
+ "LICENSE",
17
+ "README.md"
18
+ ],
19
+ "keywords": [
20
+ "newschools",
21
+ "sdk",
22
+ "nuxt",
23
+ "nuxt-module",
24
+ "react",
25
+ "svelte",
26
+ "learning",
27
+ "lms",
28
+ "api"
29
+ ],
30
+ "dependencies": {
31
+ "@nuxt/kit": "^3.13.0",
32
+ "h3": "^1.12.0",
33
+ "motion-v": "^1.7.4",
34
+ "ofetch": "^1.4.0"
35
+ },
36
+ "devDependencies": {
37
+ "@nuxt/schema": "^3.13.0",
38
+ "typescript": "^5.6.3"
39
+ },
40
+ "peerDependencies": {
41
+ "nuxt": "^3.0.0 || ^4.0.0"
42
+ },
43
+ "engines": {
44
+ "node": ">=22.0.0"
45
+ }
46
+ }