@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.
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/nuxt/src/index.ts +46 -0
- package/nuxt/src/module.ts +98 -0
- package/nuxt/src/runtime/client.ts +150 -0
- package/nuxt/src/runtime/components/OrganizationHero.vue +201 -0
- package/nuxt/src/runtime/composables/useAsyncNewSchools.ts +184 -0
- package/nuxt/src/runtime/composables/useOrganization.ts +74 -0
- package/nuxt/src/runtime/plugin.ts +104 -0
- package/nuxt/src/runtime/styles/tokens.css +112 -0
- package/nuxt/src/runtime/utils/pathResolver.ts +164 -0
- package/nuxt/src/types/api.ts +44 -0
- package/nuxt/src/types/entities.ts +197 -0
- package/nuxt/src/types/index.ts +24 -0
- package/package.json +46 -0
|
@@ -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
|
+
}
|