Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ setEnv.sh
webServer.log
.claude
locust/__pycache__

# Jasper local read-only class mirror of a connected stone (per user/stone)
.gemstone/
9 changes: 9 additions & 0 deletions Films/rowan/components/Core.ston
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
RwLoadComponent {
#name : 'Core',
#projectNames : [ ],
#componentNames : [ ],
#packageNames : [
'Films-Core'
],
#comment : 'The Films demo: the Film data class and the FilmsApi OpenAPI-documented app.'
}
12 changes: 12 additions & 0 deletions Films/rowan/project.ston
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
RwProjectSpecificationV3 {
#specName : 'project',
#projectVersion : '1.0.0',
#projectSpecPath : 'rowan',
#componentsPath : 'rowan/components',
#packagesPath : 'src',
#projectsPath : 'rowan/projects',
#specsPath : 'rowan/specs',
#packageFormat : 'tonel',
#packageConvention : 'RowanHybrid',
#comment : 'Films: the OpenAPI demo app for WebGS (Film data class + FilmsApi). Loads into its own Films symbol dictionary, matching installFilmsApi.sh.'
}
Empty file added Films/rowan/projects/README.md
Empty file.
15 changes: 15 additions & 0 deletions Films/rowan/specs/Films.ston
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RwLoadSpecificationV2 {
#projectName : 'Films',
#projectSpecFile : 'rowan/project.ston',
#componentNames : [
'Core'
],
#platformProperties : {
'gemstone' : {
'allusers' : {
#defaultSymbolDictName : 'Films'
}
}
},
#comment : 'The Films OpenAPI demo app. Loads Film + FilmsApi into the Films symbol dictionary (matches installFilmsApi.sh). Requires WebGS to be loaded first.'
}
81 changes: 81 additions & 0 deletions Films/src/Films-Core/Film.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
Class {
#name : 'Film',
#superclass : 'Object',
#instVars : [
'id',
'title',
'views'
],
#classInstVars : [
'films'
],
#category : 'Films-Core'
}

{ #category : 'unclassified' }
Film class >> data [

^#(
#(1 'Barbie' 59019108)
#(2 'The Super Mario Bros. Film' 53333425)
#(3 'Spider-Man: Across the Spid…' 35372108)
#(4 'Guardians of the Galaxy Vol 3' 33302024)
#(5 'Oppenheimer' 30250590)
#(6 'The Little Mermaid' 27659745)
#(7 'Avatar: The Way of Water' 26258614)
#(8 'Ant-Man and the Wasp: Quant…' 19898415)
#(9 'John Wick: Chapter 4' 17359165)
#(10 'Sound of Freedom' 17085161)
)
]

{ #category : 'unclassified' }
Film class >> films [

films ifNil: [
films := self data collect: [:row |
self new initialize: row; yourself.
].
].
^films
]

{ #category : 'unclassified' }
Film class >> withId: anInteger [

^self films
detect: [:each | each id = anInteger]
ifNone: [nil]
]

{ #category : 'initialization' }
Film >> initialize: anArray [

id := anArray at: 1.
title := anArray at: 2.
views := anArray at: 3.
]

{ #category : 'accessors' }
Film >> id [

^id
]

{ #category : 'accessors' }
Film >> title [

^title
]

{ #category : 'accessors' }
Film >> views [

^views
]

{ #category : 'accessors' }
Film >> views: anInteger [

views := anInteger
]
130 changes: 130 additions & 0 deletions Films/src/Films-Core/FilmsApi.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
"Demo app showing OpenAPI-documented routes via DocumentedRouter.

Launch with: FilmsApi runHttp.
Then visit: http://localhost:8888/docs"
Class {
#name : 'FilmsApi',
#superclass : 'Object',
#category : 'Films-Core'
}

{ #category : 'launching' }
FilmsApi class >> runHttp [
"
FilmsApi runHttp.
"

^self runHttpOnPort: 8888
]

{ #category : 'launching' }
FilmsApi class >> runHttpOnPort: anInteger [
"
FilmsApi runHttpOnPort: 8888.
"

HttpListener new
listenBacklog: 200;
port: anInteger;
server: HttpServer;
router: self defaultRouter;
run
]

{ #category : 'routes' }
FilmsApi class >> defaultRouter [
"
A configured DocumentedRouter with the Films endpoints registered and the
OpenAPI spec populated. Visit /openapi.json for the spec or /docs for Swagger UI.
"

| router filmSchema |
router := DocumentedRouter new.
router spec
title: 'Films API';
version: '1.0.0';
description: 'A demo of OpenAPI-documented routes served by WebGS.';
server: 'http://localhost:8888' description: 'Local development server'.

filmSchema := OpenApiSchema object
property: 'id' type: 'integer';
property: 'title' type: 'string';
property: 'views' type: 'integer';
required: #('id' 'title' 'views');
yourself.
router spec schema: 'Film' definition: filmSchema.

router spec schema: 'Error' definition: (OpenApiSchema object
property: 'error' type: 'string';
required: #('error');
yourself).

self registerListRouteOn: router.
self registerGetByIdRouteOn: router.

^router
]

{ #category : 'routes' }
FilmsApi class >> registerGetByIdRouteOn: aRouter [

aRouter
get: '/films/:id'
do: [:request :response :id |
| film |
film := Film withId: id asInteger.
film ifNil: [
response
code: 404;
content: (Dictionary new
at: 'error' put: 'Film with id ' , id , ' not found';
yourself) asJson;
contentType: 'application/json; charset=UTF-8'.
] ifNotNil: [
response
content: (self filmAsDictionary: film) asJson;
contentType: 'application/json; charset=UTF-8'.
].
]
operation: (OpenApiOperation new
summary: 'Get a film by id';
description: 'Returns a single film, or a 404 error if no film has the given id.';
operationId: 'getFilmById';
tag: 'films';
response: 200 description: 'The requested film' schema: (OpenApiSchema ref: 'Film');
response: 404 description: 'No film with that id' schema: (OpenApiSchema ref: 'Error');
yourself).
]

{ #category : 'routes' }
FilmsApi class >> registerListRouteOn: aRouter [

aRouter
get: '/films'
do: [:request :response |
| rows |
rows := Film films collect: [:each | self filmAsDictionary: each].
response
content: rows asArray asJson;
contentType: 'application/json; charset=UTF-8'.
]
operation: (OpenApiOperation new
summary: 'List all films';
description: 'Returns the full collection of films known to the server.';
operationId: 'listFilms';
tag: 'films';
response: 200
description: 'A list of films'
schema: (OpenApiSchema array: (OpenApiSchema ref: 'Film'));
yourself).
]

{ #category : 'utilities' }
FilmsApi class >> filmAsDictionary: aFilm [

^Dictionary new
at: 'id' put: aFilm id;
at: 'title' put: aFilm title;
at: 'views' put: aFilm views;
yourself
]
1 change: 1 addition & 0 deletions Films/src/Films-Core/package.st
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Package { #name : 'Films-Core' }
4 changes: 4 additions & 0 deletions Films/src/Films-Core/properties.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
#format : 'tonel',
#convention : 'RowanHybrid'
}
4 changes: 4 additions & 0 deletions Films/src/properties.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
#format : 'tonel',
#convention : 'RowanHybrid'
}
76 changes: 76 additions & 0 deletions installRowan.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash -e
#
# Load WebGS into GemStone as a Rowan project (Tonel source under ./src, load
# specs under ./rowan/specs). This is the Rowan replacement for the topaz
# fileout performed by install.sh.
#
# The optional Films OpenAPI demo is a Rowan project of its own (./Films),
# loaded into its own Films symbol dictionary — the Rowan replacement for
# installFilmsApi.sh. Pass --with-films (or films) to load it too.
#
# Requires:
# * A running, Rowan-enabled stone.
# * GEMSTONE / PATH set (see README).
# * .topazini (here or in $HOME), e.g.:
# set user DataCurator pass swordfish gems gs64stone
#
# Usage:
# ./installRowan.sh # WebGS framework + OpenAPI + Sample (== install.sh)
# ./installRowan.sh --with-films # the above, plus the Films demo (== install.sh + installFilmsApi.sh)
#
cd "$(dirname "$0")"
REPO="$PWD"
PARENT="$(dirname "$REPO")"

FILMS_LOAD=""
FILMS_MSG=""
case "${1:-}" in
--with-films|films|--films)
FILMS_LOAD="load value: 'file:$REPO/Films/rowan/specs/Films.ston' value: '$REPO' value: 'Films'."
FILMS_MSG="msg := msg , '; loaded Films (' , (rowan projectNamed: 'Films') packageNames size printString , ' packages) into symbolDict Films'."
;;
"") ;;
*) echo "usage: $0 [--with-films]" >&2; exit 2 ;;
esac

topaz -lq << EOF
iferr 1 stk
iferr 2 output pop
iferr 3 stk
iferr 4 abort
iferr 5 logout
iferr 6 exit 1
set cachename WebGS_Rowan
login
output push WebGS.out only
fileformat utf8
run
| specClass load rowan msg |
specClass := (System myUserProfile symbolList resolveSymbol: #'RwSpecification') ifNil: [
^'ERROR: Rowan (RwSpecification) is not installed in this stone; cannot load WebGS as a Rowan project.'
] value.
load := [:url :home :name | | spec |
spec := specClass fromUrl: url.
spec projectsHome: home.
spec resolve load.
name].
"WebGS project -> WebGS symbol dictionary (== install.sh)"
load value: 'file:$REPO/rowan/specs/WebGS.ston' value: '$PARENT' value: 'WebGS'.
$FILMS_LOAD
System commit.
rowan := (System myUserProfile symbolList resolveSymbol: #'Rowan') value.
msg := 'Loaded WebGS (' , (rowan projectNamed: 'WebGS') packageNames size printString , ' packages) into symbolDict WebGS'.
$FILMS_MSG
msg
%
output pop
errorCount
logout
exit 0
EOF

if [ "$?" == "0" ]; then
echo "Rowan load finished. Review WebGS.out for details."
else
echo "Rowan load of WebGS failed. Please review WebGS.out and try again!"
fi
11 changes: 11 additions & 0 deletions rowan/components/Core.ston
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RwLoadComponent {
#name : 'Core',
#projectNames : [ ],
#componentNames : [ ],
#packageNames : [
'WebGS-Core',
'WebGS-OpenApi',
'WebGS-Sample'
],
#comment : 'The WebGS HTTP server framework, its OpenAPI documentation support, and the Sample demo app (matches install.sh).'
}
12 changes: 12 additions & 0 deletions rowan/project.ston
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
RwProjectSpecificationV3 {
#specName : 'project',
#projectVersion : '1.0.0',
#projectSpecPath : 'rowan',
#componentsPath : 'rowan/components',
#packagesPath : 'src',
#projectsPath : 'rowan/projects',
#specsPath : 'rowan/specs',
#packageFormat : 'tonel',
#packageConvention : 'RowanHybrid',
#comment : 'WebGS: a framework for building web application back-ends in GemStone/S 64 Bit Smalltalk.'
}
Empty file added rowan/projects/README.md
Empty file.
15 changes: 15 additions & 0 deletions rowan/specs/WebGS.ston
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
RwLoadSpecificationV2 {
#projectName : 'WebGS',
#projectSpecFile : 'rowan/project.ston',
#componentNames : [
'Core'
],
#platformProperties : {
'gemstone' : {
'allusers' : {
#defaultSymbolDictName : 'WebGS'
}
}
},
#comment : 'Base WebGS server: the HTTP framework plus OpenAPI support (matches install.sh).'
}
Loading